1 Tools & Libraries

library(scales)
library(ez)
library(MASS)
library(effsize)
library(rcompanion)
library(ARTool)
library(emmeans)
library(HH)
library(rstatix)
library(tidyverse)
library(DescTools)


normal_error <- function(d) {
  n <- length(d)
  qnorm(0.975) * (sd(d) /sqrt(n))
}

summary_with_ci <- function(d) {
  tibble(
    MeanValue = mean(d),
    ErrorValue = normal_error(d),
    LowerValue = MeanValue - ErrorValue,
    UpperValue = MeanValue + ErrorValue
  )
}

2 Load data

trials <- read_csv(
  "./data1.csv",
  col_types = cols(
    Participant = col_factor(),
    Guide = col_factor(),
    Set = col_factor(),
    Phase = col_factor(),
    Block = col_factor(),
    Trial = col_character(),
    TrialName = col_factor(),
    TriggeredName = col_factor(),
    Result = col_logical(),
    Mode = col_factor(),
    RestartCount = col_double(),
    DrawTime = col_double(),
    NoviceTime = col_double(),
    EndTime = col_double(),
    TriggerDuration = col_double(),
    GripDuration = col_double(),
    IdleDuration = col_double()
  )
) %>%
  filter(Participant != "P3" & Participant != "P6") %>%
  mutate(
    Participant = droplevels(Participant),
    Block = factor(Block),
    InputTime = EndTime-NoviceTime,
    IsOutlier = Phase == "Training" &
           EndTime > mean(EndTime[Phase == "Training"]) + 3 * sd(EndTime[Phase == "Training"]))

trials

# Number of outliers
a = sum(trials$IsOutlier == TRUE)
b = sum(trials$Phase == "Training")
(a/b)*100
[1] 2.314815

3 TIME

3.1 Trial Time

trialtime_p_summary <- trials %>%
  filter(Mode == "Novice", Phase == "Training" & Result == TRUE & IsOutlier == FALSE) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(EndTime), .groups="drop")

# because P4 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P4", "Sheet", "Training", "B3", 12.201982)
trialtime_p_summary = rbind(trialtime_p_summary, newRow)
# because P11 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P11", "Sheet", "Training", "B3", 9.1895835)
# merge new row into table
trialtime_p_summary = rbind(trialtime_p_summary, newRow)
# convert from character to numbers
trialtime_p_summary$Mean <- as.numeric(as.character(trialtime_p_summary$Mean))
trialtime_p_summary

trialtime_octo <- subset(trialtime_p_summary,  Guide == "Octo", Mean, drop = TRUE)
trialtime_sheet <- subset(trialtime_p_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(trialtime_sheet, trialtime_octo)
  meandiff     lwr.ci     upr.ci 
 0.9103542 -0.3476703  2.1683788 
trialtime_b1 <- subset(trialtime_p_summary,  Block == "B1", Mean, drop = TRUE)
trialtime_b2 <- subset(trialtime_p_summary,  Block == "B2", Mean, drop = TRUE)
trialtime_b3 <- subset(trialtime_p_summary,  Block == "B3", Mean, drop = TRUE)
MeanDiffCI(trialtime_b2, trialtime_b1)
  meandiff     lwr.ci     upr.ci 
-1.6326259 -3.0862784 -0.1789734 
MeanDiffCI(trialtime_b3, trialtime_b1)
  meandiff     lwr.ci     upr.ci 
-1.9928490 -3.4778429 -0.5078552 
trialtime_summary <- trialtime_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
trialtime_summary

3.1.1 Graph

pd <- position_dodge(0.4)

ggplot(data=trialtime_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=format(round(MeanValue,1),nsmall=1), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(trialtime_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(trialtime_summary$Guide=="Octo", -0.4, 0.4)
  )+
  expand_limits(y=c(0,11.5))+
  labs(x="Block", y="Time (s)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_shape_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_linetype(labels=c("OCTOPOCUS","CRIBSHEET"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(legend.background = element_blank(), legend.title = element_blank(),
        legend.position = c(0.5, 0.1), legend.direction = "horizontal",
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

3.1.2 Assumptions

Shapiro test p < 0.05. The distribution of the residuals is not normal.

m = aov(Mean ~ Block*Guide + Error(Participant), data = trialtime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.94415, p-value = 0.008342
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

3.1.3 Data Transformation

Shapiro test p > 0.05. The distribution of the residuals is now normal.

trialtime_p_summary$TransVal = log(trialtime_p_summary$Mean)
m = aov(TransVal ~ Block*Guide + Error(Participant), data = trialtime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.96365, p-value = 0.07104
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

3.1.4 ANOVA

ezANOVA(
  trialtime_p_summary,
  dv = log(Mean),
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

3.1.5 Pairwise Comparison

pairwise.t.test(trialtime_p_summary$TransVal, 
                trialtime_p_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  trialtime_p_summary$TransVal and trialtime_p_summary$Block 

   B1     B2    
B2 0.0019 -     
B3 0.0050 1.0000

P value adjustment method: bonferroni 

3.2 Reaction Time

reactiontime_p_summary <- trials %>%
  filter(Mode == "Novice" & Phase == "Training" & Result == TRUE & IsOutlier == FALSE) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(NoviceTime), .groups="drop")

# because P4 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P4", "Sheet", "Training", "B3", 0.93730355)
reactiontime_p_summary = rbind(reactiontime_p_summary, newRow)
# because P11 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P11", "Sheet", "Training", "B3", 1.48358335)
# merge new row into table
reactiontime_p_summary = rbind(reactiontime_p_summary, newRow)
# convert from character to numbers
reactiontime_p_summary$Mean <- as.numeric(as.character(reactiontime_p_summary$Mean))
reactiontime_p_summary

reactiontime_octo <- subset(reactiontime_p_summary,  Guide == "Octo", Mean, drop = TRUE)
reactiontime_sheet <- subset(reactiontime_p_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(reactiontime_sheet, reactiontime_octo)
  meandiff     lwr.ci     upr.ci 
-0.8840140 -1.0874074 -0.6806207 
reactiontime_summary <- reactiontime_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
reactiontime_summary

3.2.1 Graph

pd <- position_dodge(0.4)

ggplot(data=reactiontime_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=format(round(MeanValue,1),nsmall=1), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(reactiontime_summary$Guide=="Octo", -0.1, 0.1),
            nudge_y=ifelse(reactiontime_summary$Guide=="Octo", 0.8, -0.8)
  )+
  expand_limits(y=c(0,11.5))+
  labs(x="Block", y="Time (s)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"))+
  # facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        legend.position = "none",
        # legend.position = c(0.8, 0.85), legend.direction = "vertical",
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

3.2.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ Block*Guide + Error(Participant), data = reactiontime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.9734, p-value = 0.2134
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

3.2.3 ANOVA

ezANOVA(
  reactiontime_p_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

3.3 Input Time

inputtime_p_summary <- trials %>%
  filter(Mode == "Novice", Phase == "Training" & Result == TRUE & IsOutlier == FALSE) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(InputTime), .groups="drop")

# because P4 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P4", "Sheet", "Training", "B3", 11.2646785)
inputtime_p_summary = rbind(inputtime_p_summary, newRow)
# because P11 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P11", "Sheet", "Training", "B3", 7.706)
# merge new row into table
inputtime_p_summary = rbind(inputtime_p_summary, newRow)
# convert from character to numbers
inputtime_p_summary$Mean <- as.numeric(as.character(inputtime_p_summary$Mean))
inputtime_p_summary

inputtime_octo <- subset(inputtime_p_summary,  Guide == "Octo", Mean, drop = TRUE)
inputtime_sheet <- subset(inputtime_p_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(inputtime_sheet, inputtime_octo)
 meandiff    lwr.ci    upr.ci 
1.7943683 0.5364499 3.0522866 
inputtime_b1 <- subset(inputtime_p_summary,  Block == "B1", Mean, drop = TRUE)
inputtime_b2 <- subset(inputtime_p_summary,  Block == "B2", Mean, drop = TRUE)
inputtime_b3 <- subset(inputtime_p_summary,  Block == "B3", Mean, drop = TRUE)
MeanDiffCI(inputtime_b2, inputtime_b1)
   meandiff      lwr.ci      upr.ci 
-1.52211153 -3.01745734 -0.02676572 
MeanDiffCI(inputtime_b3, inputtime_b1)
  meandiff     lwr.ci     upr.ci 
-1.9165457 -3.4683654 -0.3647261 
inputtime_summary <- inputtime_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
inputtime_summary
NA

3.3.1 Graph

pd <- position_dodge(0.4)

ggplot(data=inputtime_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=format(round(MeanValue,1),nsmall=1), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(inputtime_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(inputtime_summary$Guide=="Octo", -0.4, 0.4)
  )+
  expand_limits(y=c(0,11.5))+
  labs(x="Block", y="Time (s)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"))+
  # facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(legend.position = "none",
        #legend.position = c(0.8, 0.15), legend.direction = "vertical",
        # legend.background = element_blank(),
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

3.3.2 Assumptions

Shapiro test p < 0.05. The distribution of the residuals is not normal.

m = aov(Mean ~ Block*Guide + Error(Participant), data = inputtime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.9503, p-value = 0.01609
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

3.3.3 Data Transformation

Shapiro test p > 0.05. The distribution of the residuals is now normal.

inputtime_p_summary$TransVal = sqrt(inputtime_p_summary$Mean)
m = aov(TransVal ~ Block*Guide + Error(Participant), data = inputtime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.96032, p-value = 0.04876
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

3.3.4 ANOVA

ezANOVA(
  inputtime_p_summary,
  dv = TransVal,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

3.3.5 Pairwise Comparison

pairwise.t.test(inputtime_p_summary$TransVal, 
                inputtime_p_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  inputtime_p_summary$TransVal and inputtime_p_summary$Block 

   B1     B2    
B2 0.0077 -     
B3 0.0312 1.0000

P value adjustment method: bonferroni 

4 ACCURACY

4.1 Overall Training

accuracy_overalltraining_p_summary <- trials %>%
  filter(Phase == "Training" & !IsOutlier) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(Result), .groups="drop")
accuracy_overalltraining_p_summary

overalltrainingacc_octo <- subset(accuracy_overalltraining_p_summary,  Guide == "Octo", Mean, drop = TRUE)
overalltrainingacc_sheet <- subset(accuracy_overalltraining_p_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(overalltrainingacc_sheet, overalltrainingacc_octo)
   meandiff      lwr.ci      upr.ci 
-0.13767985 -0.17744954 -0.09791017 
accuracy_overalltraining_summary <- accuracy_overalltraining_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))

accuracy_overalltraining_summary

4.1.1 Graph

pd <- position_dodge(0.4)

ggplot(data=accuracy_overalltraining_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(accuracy_overalltraining_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(accuracy_overalltraining_summary$Guide=="Octo", 0.1, -0.1)
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Block", y="Accuracy (%)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_shape_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_linetype(labels=c("OCTOPOCUS","CRIBSHEET"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(legend.background = element_blank(), legend.title = element_blank(),
        legend.position = c(0.5, 0.1), legend.direction = "horizontal",
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

4.1.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ Block*Guide + Error(Participant), data = accuracy_overalltraining_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.97962, p-value = 0.4125
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

4.1.3 ANOVA

ezANOVA(
  accuracy_overalltraining_p_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

4.2 Expert Training

accuracy_p_expert_summary <- trials %>%
  filter(Phase == "Training" & Mode == "Expert" & !IsOutlier) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(Result), .groups="drop")
accuracy_p_expert_summary

expertacc_octo <- subset(accuracy_p_expert_summary,  Guide == "Octo", Mean, drop = TRUE)
expertacc_sheet <- subset(accuracy_p_expert_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(expertacc_sheet, expertacc_octo)
   meandiff      lwr.ci      upr.ci 
-0.10394979 -0.16141056 -0.04648901 
expertacc_b1 <- subset(accuracy_p_expert_summary,  Block == "B1", Mean, drop = TRUE)
expertacc_b2 <- subset(accuracy_p_expert_summary,  Block == "B2", Mean, drop = TRUE)
expertacc_b3 <- subset(accuracy_p_expert_summary,  Block == "B3", Mean, drop = TRUE)
MeanDiffCI(expertacc_b3, expertacc_b2)
   meandiff      lwr.ci      upr.ci 
-0.10574691 -0.17631257 -0.03518125 
accuracy_expert_summary <- accuracy_p_expert_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
accuracy_expert_summary

4.2.1 Graph

ggplot(data=accuracy_expert_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(accuracy_expert_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(accuracy_expert_summary$Guide=="Octo", 0.1, -0.1)
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1)) +
  labs(x="Block", y="Accuracy (%)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        legend.position = "none",
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

4.2.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ Block*Guide + Error(Participant), data = accuracy_p_expert_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.98827, p-value = 0.8341
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

4.2.3 ANOVA

ezANOVA(
  accuracy_p_expert_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

4.2.4 Pairwise Comparison

pairwise.t.test(accuracy_p_expert_summary$Mean, 
                accuracy_p_expert_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  accuracy_p_expert_summary$Mean and accuracy_p_expert_summary$Block 

   B1    B2   
B2 0.610 -    
B3 0.306 0.011

P value adjustment method: bonferroni 

4.3 Novice Training

accuracy_p_novice_summary <- trials %>%
  filter(Phase == "Training" & Mode == "Novice" & !IsOutlier) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(Result), .groups="drop")

# because P11 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P11", "Sheet", "Training", "B3", 0.67857145)
# merge new row into table
accuracy_p_novice_summary = rbind(accuracy_p_novice_summary, newRow)
# convert from character to numbers
accuracy_p_novice_summary$Mean <- as.numeric(as.character(accuracy_p_novice_summary$Mean))

accuracy_p_novice_summary

noviceacc_octo <- subset(accuracy_p_novice_summary,  Guide == "Octo", Mean, drop = TRUE)
noviceacc_sheet <- subset(accuracy_p_novice_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(noviceacc_sheet, noviceacc_octo)
  meandiff     lwr.ci     upr.ci 
-0.2014409 -0.2824296 -0.1204522 
accuracy_novice_summary <- accuracy_p_novice_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
accuracy_novice_summary

4.3.1 Graph

pd <- position_dodge(0.4)

ggplot(data=accuracy_novice_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(accuracy_novice_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(accuracy_novice_summary$Guide=="Octo", 0.05, -0.05)
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Block", y="Accuracy (%)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        legend.position = "none",
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

4.3.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ Block*Guide + Error(Participant), data = accuracy_p_novice_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.96389, p-value = 0.07298
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

4.3.3 ANOVA

ezANOVA(
  accuracy_p_novice_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

4.4 Guess (Pre-Test)

accuracy_pretest_p_summary <- trials %>%
  filter(Phase == "PreTest" & !IsOutlier) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(Result), .groups="drop")
accuracy_pretest_p_summary

accuracy_pretest_summary <- accuracy_pretest_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))

pretestacc_octo <- subset(accuracy_pretest_p_summary,  Guide == "Octo", Mean, drop = TRUE)
pretestacc_sheet <- subset(accuracy_pretest_p_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(pretestacc_sheet, pretestacc_octo)
    meandiff       lwr.ci       upr.ci 
 0.005208333 -0.039921417  0.050338084 
accuracy_pretest_summary

4.4.1 Graph

ggplot(data=accuracy_pretest_summary, aes(x=Guide, y=MeanValue, fill = Guide)) +
  geom_bar(size=3,stat="identity")+
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide),
            show.legend = FALSE,
            size=4, nudge_y = 0.1
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Guide", y="Accuracy (%)")+
  scale_x_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_fill_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_shape_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_linetype(labels=c("OCTOPOCUS","CRIBSHEET"))+
  theme_bw(base_size = 12)+
  theme(legend.position = "none", legend.direction = "horizontal",
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

4.4.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ Guide + Error(Participant), data = accuracy_pretest_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.91721, p-value = 0.2637
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

4.4.3 ANOVA

ezANOVA(
  accuracy_pretest_p_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide)
)
$ANOVA
NA

4.5 Recall (Test)

accuracy_test_p_summary <- trials %>%
  filter(Phase == "Test" & !IsOutlier) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(Result), .groups="drop")
accuracy_test_p_summary

maintest_octo <- subset(accuracy_test_p_summary,  Guide == "Octo", Mean, drop = TRUE)
maintest_sheet <- subset(accuracy_test_p_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(maintest_sheet, maintest_octo)
    meandiff       lwr.ci       upr.ci 
-0.006944444 -0.114260087  0.100371198 
accuracy_test_summary <- accuracy_test_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))

acctest_b1 <- subset(accuracy_test_p_summary,  Block == "B1", Mean, drop = TRUE)
acctest_b2 <- subset(accuracy_test_p_summary,  Block == "B2", Mean, drop = TRUE)
acctest_b3 <- subset(accuracy_test_p_summary,  Block == "B3", Mean, drop = TRUE)
MeanDiffCI(acctest_b2, acctest_b1)
  meandiff     lwr.ci     upr.ci 
0.20312500 0.09830948 0.30794052 
MeanDiffCI(acctest_b3, acctest_b2)
  meandiff     lwr.ci     upr.ci 
0.15625000 0.05694772 0.25555228 
accuracy_test_summary

4.5.1 Graph

pd <- position_dodge(0.4)

ggplot(data=accuracy_test_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide),
            size=4, nudge_x=ifelse(accuracy_test_summary$Guide=="Octo", -0.4, 0.4),
            nudge_y=ifelse(accuracy_test_summary$Guide=="Octo", 0.1, -0.1)
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Block", y="Accuracy (%)")+
  scale_x_discrete(labels=c("B1-Test", "B2-Test", "B3-Test"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_shape_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_linetype(labels=c("OCTOPOCUS","CRIBSHEET"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(legend.background = element_blank(), legend.title = element_blank(),
        legend.position = c(0.5, 0.1), legend.direction = "horizontal",
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

4.5.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ Block*Guide + Error(Participant), data = accuracy_test_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.98614, p-value = 0.7292
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

4.5.3 ANOVA

ezANOVA(
  accuracy_test_p_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

4.5.4 Pairwise Comparison

pairwise.t.test(accuracy_test_p_summary$Mean, 
                accuracy_test_p_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  accuracy_test_p_summary$Mean and accuracy_test_p_summary$Block 

   B1      B2     
B2 0.00016 -      
B3 9.3e-08 0.00062

P value adjustment method: bonferroni 

4.6 Incidental Learning (Post-test)

# excluding targets
accuracy_posttest_p_summary <- trials %>%
  filter(Phase == "PostTest" & !IsOutlier) %>%
  filter(TrialName != "Abu Dhabi" & TrialName != "Amsterdam" & TrialName != "Dubai" & TrialName != "Los Angeles" & TrialName != "Madrid" & TrialName != "Paris" & TrialName != "Singapore" & TrialName != "Tokyo" & TrialName != "Austin" & TrialName != "Doha" & TrialName != "Frankfurt" & TrialName != "Houston" & TrialName != "Milan" & TrialName != "Prague" & TrialName != "Seoul" & TrialName != "Toronto") %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Mean = mean(Result), .groups="drop")
accuracy_posttest_p_summary

accuracyposttest_octo <- subset(accuracy_posttest_p_summary,  Guide == "Octo", Mean, drop = TRUE)
accuracyposttest_sheet <- subset(accuracy_posttest_p_summary,  Guide == "Sheet", Mean, drop = TRUE)
MeanDiffCI(accuracyposttest_octo, accuracyposttest_sheet)
   meandiff      lwr.ci      upr.ci 
-0.06250000 -0.21695935  0.09195935 
accuracy_posttest_summary <- accuracy_posttest_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
accuracy_posttest_summary

4.6.1 Graph

ggplot(data=accuracy_posttest_summary, aes(x=Guide, y=MeanValue, fill = Guide)) +
  geom_bar(size=3,stat="identity")+
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide),
            show.legend = FALSE,
            size=4, nudge_y = 0.05, nudge_x = 0.3
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Guide", y="Accuracy (%)")+
  scale_x_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_fill_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_shape_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_linetype(labels=c("OCTOPOCUS","CRIBSHEET"))+
  theme_bw(base_size = 12)+
  theme(legend.position = "none", legend.direction = "horizontal",
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

4.6.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ Guide + Error(Participant), data = accuracy_posttest_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.97556, p-value = 0.9595
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

4.6.3 ANOVA

ezANOVA(
  accuracy_posttest_p_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide)
)
$ANOVA
NA

4.7 Learning Curve (combined, only 8 trained gestures)

targets <- c("Abu Dhabi", "Amsterdam", "Dubai", "Los Angeles", "Madrid", "Paris", "Singapore", "Tokyo", "Austin", "Doha", "Frankfurt", "Houston", "Milan", "Prague", "Seoul", "Toronto")

curve_p_summary <- trials %>%
  filter(TrialName %in% targets & Phase!="Training" & !IsOutlier) %>%
  mutate(PhaseName = ifelse(Phase=="Test" & Block=="B1", "Test B1",
                    ifelse(Phase=="Test" & Block=="B2", "Test B2",
                    ifelse(Phase=="Test" & Block=="B3", "Test B3",
                    ifelse(Phase=="PreTest", "PreTest",
                    ifelse(Phase=="PostTest", "PostTest",NA)))))) %>%
  mutate(PhaseName = fct_relevel(PhaseName, 
            "PreTest", "Test B1", "Test B2", "Test B3", "PostTest")) %>%
  mutate(PhaseName = as.factor(PhaseName)) %>%
  group_by(Participant, Guide, PhaseName) %>%
  summarize(Mean = mean(Result), .groups="drop")
curve_p_summary

curve_summary <- curve_p_summary %>%
  group_by(Guide, PhaseName) %>%
  summarize(summary_with_ci(Mean), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
curve_summary


curve_testB3 <- subset(curve_p_summary,  PhaseName == "Test B3", Mean, drop = TRUE)
curve_posttest <- subset(curve_p_summary,  PhaseName == "PostTest", Mean, drop = TRUE)
MeanDiffCI(curve_posttest, curve_testB3)
    meandiff       lwr.ci       upr.ci 
-0.088541667 -0.180952498  0.003869164 

4.7.1 Graph

pd <- position_dodge(0.4)

ggplot(data=curve_summary, aes(x=PhaseName, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide),
            size=4, nudge_x=ifelse(curve_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(curve_summary$Guide=="Octo", 0.1, -0.1),
            show.legend = FALSE
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Phase", y="Accuracy (%)")+
  # scale_x_discrete(labels=c("B1-Test", "B2-Test", "B3-Test"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_shape_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_linetype(labels=c("OCTOPOCUS","CRIBSHEET"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(legend.background = element_blank(), legend.title = element_blank(),
        legend.position = c(0.5, 0.1), legend.direction = "horizontal",
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

4.7.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(Mean ~ PhaseName*Guide + Error(Participant), data = curve_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.98288, p-value = 0.1804
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

4.7.3 ANOVA

# curve_p_summary_new = filter(curve_p_summary, PhaseName=="Test B3" | PhaseName=="PostTest")
# curve_p_summary_new

ezANOVA(
  curve_p_summary,
  dv = Mean,
  wid = Participant,
  within = c(Guide, PhaseName)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

4.7.4 Pairwise Comparison

pairwise.t.test(curve_p_summary$Mean, 
                curve_p_summary$PhaseName, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  curve_p_summary$Mean and curve_p_summary$PhaseName 

         PreTest Test B1 Test B2 Test B3
Test B1  1.5e-07 -       -       -      
Test B2  2.9e-11 0.00054 -       -      
Test B3  1.2e-13 3.1e-07 0.00206 -      
PostTest 2.8e-14 3.1e-06 1.00000 0.06527

P value adjustment method: bonferroni 

5 OTHERS

5.1 Expert Mode Rate (during Training)

expertproportion_p_summary <- trials %>%
  filter(Phase == "Training" & !IsOutlier) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(ExpertCount = sum(Mode=="Expert"), 
            Total = sum(Mode=="Novice") + sum(Mode=="Expert"),
            ExpertPercent = (sum(Mode=="Expert")/Total),
            .groups="drop")
expertproportion_p_summary

expertpro_octo <- subset(expertproportion_p_summary,  Guide == "Octo", ExpertPercent, drop = TRUE)
expertpro_sheet <- subset(expertproportion_p_summary,  Guide == "Sheet", ExpertPercent, drop = TRUE)
MeanDiffCI(expertpro_sheet, expertpro_octo)
   meandiff      lwr.ci      upr.ci 
 0.08249224 -0.01075320  0.17573767 
expertpro_b1 <- subset(expertproportion_p_summary,  Block == "B1", ExpertPercent, drop = TRUE)
expertpro_b2 <- subset(expertproportion_p_summary,  Block == "B2", ExpertPercent, drop = TRUE)
expertpro_b3 <- subset(expertproportion_p_summary,  Block == "B3", ExpertPercent, drop = TRUE)
MeanDiffCI(expertpro_b2, expertpro_b1)
  meandiff     lwr.ci     upr.ci 
0.13864872 0.04034435 0.23695309 
MeanDiffCI(expertpro_b3, expertpro_b1)
  meandiff     lwr.ci     upr.ci 
0.20440037 0.09425377 0.31454697 
expertproportion_summary <- expertproportion_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(ExpertPercent), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
expertproportion_summary

5.1.1 Graph

pd <- position_dodge(0.4)

ggplot(data=expertproportion_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide),
            size=4, nudge_x=ifelse(expertproportion_summary$Guide=="Octo", -0.35, 0.35),
            nudge_y=ifelse(expertproportion_summary$Guide=="Octo", -0.15, 0.15)
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Block", y="Usage Rate (%)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"),labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_shape_discrete(labels=c("OCTOPOCUS","CRIBSHEET"))+
  scale_linetype(labels=c("OCTOPOCUS","CRIBSHEET"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(legend.background = element_blank(), legend.title = element_blank(),
        legend.position = c(0.5, 0.1), legend.direction = "horizontal",
        panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

5.1.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(ExpertPercent ~ Block*Guide + Error(Participant), data = expertproportion_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.96087, p-value = 0.05191
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.1.3 ANOVA

ezANOVA(
  expertproportion_p_summary,
  dv = ExpertPercent,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

5.1.4 Pairwise Comparison

pairwise.t.test(expertproportion_p_summary$ExpertPercent, 
                expertproportion_p_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  expertproportion_p_summary$ExpertPercent and expertproportion_p_summary$Block 

   B1      B2     
B2 0.00012 -      
B3 0.00081 0.25270

P value adjustment method: bonferroni 

5.2 Exploration Mode Rate (during Training)

exploreprop_p_summary <- trials %>%
  filter(Phase == "Training" & !IsOutlier) %>%
  mutate(isExploring = ifelse(GripDuration>0, 1, 0)) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Frequency = sum(isExploring),
            Total = sum(Mode=="Novice") + sum(Mode=="Expert"),
            Proportion = (Frequency/Total),
            .groups="drop")
exploreprop_p_summary

exploreprop_summary <- exploreprop_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(Proportion), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
exploreprop_summary

explorepro_octo <- subset(exploreprop_p_summary,  Guide == "Octo", Proportion, drop = TRUE)
explorepro_sheet <- subset(exploreprop_p_summary,  Guide == "Sheet", Proportion, drop = TRUE)
MeanDiffCI(explorepro_sheet, explorepro_octo)
 meandiff    lwr.ci    upr.ci 
0.2374574 0.1710811 0.3038337 
explorepro_b1 <- subset(exploreprop_p_summary,  Block == "B1", Proportion, drop = TRUE)
explorepro_b2 <- subset(exploreprop_p_summary,  Block == "B2", Proportion, drop = TRUE)
explorepro_b3 <- subset(exploreprop_p_summary,  Block == "B3", Proportion, drop = TRUE)
MeanDiffCI(explorepro_b2, explorepro_b1)
   meandiff      lwr.ci      upr.ci 
-0.14020445 -0.23863576 -0.04177314 
MeanDiffCI(explorepro_b3, explorepro_b2)
   meandiff      lwr.ci      upr.ci 
-0.07844066 -0.17151924  0.01463792 

5.2.1 Graph

pd <- position_dodge(0.4)

ggplot(data=exploreprop_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(exploreprop_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(exploreprop_summary$Guide=="Octo", -0.05, 0.05)
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Block", y="Usage Rate (%)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        legend.position = "none",
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

5.2.2 Assumptions

Shapiro test p < 0.05. The distribution of the residuals is not normal.

m = aov(Proportion ~ Block*Guide + Error(Participant), data = exploreprop_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.94881, p-value = 0.01369
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.2.3 Data Transformation

Shapiro test p > 0.05. The distribution of the residuals is now normal.

exploreprop_p_summary$TransVal = sqrt(exploreprop_p_summary$Proportion)
m = aov(TransVal ~ Block*Guide + Error(Participant), data = exploreprop_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.98542, p-value = 0.692
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.2.4 ANOVA

ezANOVA(
  exploreprop_p_summary,
  dv = TransVal,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

5.2.5 Pairwise Comparison

pairwise.t.test(exploreprop_p_summary$TransVal, 
                exploreprop_p_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  exploreprop_p_summary$TransVal and exploreprop_p_summary$Block 

   B1      B2   
B2 1.6e-05 -    
B3 1.2e-07 0.012

P value adjustment method: bonferroni 

5.3 OCTO Exploration Mode Rate (during Training)

exploreprop_octo_p_summary <- trials %>%
  filter(Guide == "Octo" & Phase == "Training" & !IsOutlier) %>%
  mutate(isExploring = ifelse(GripDuration>0, 1, 0)) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(Frequency = sum(isExploring),
            Total = sum(Mode=="Novice") + sum(Mode=="Expert"),
            Proportion = (Frequency/Total),
            .groups="drop")
exploreprop_octo_p_summary

exploreprop_octo_summary <- exploreprop_octo_p_summary %>%
  group_by(Guide,Block) %>%
  summarize(summary_with_ci(Proportion), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
exploreprop_octo_summary

explorepro_octo_b1 <- subset(exploreprop_octo_p_summary,  Block == "B1", Proportion, drop = TRUE)
explorepro_octo_b2 <- subset(exploreprop_octo_p_summary,  Block == "B2", Proportion, drop = TRUE)
explorepro_octo_b3 <- subset(exploreprop_octo_p_summary,  Block == "B3", Proportion, drop = TRUE)
MeanDiffCI(explorepro_octo_b2, explorepro_octo_b1)
   meandiff      lwr.ci      upr.ci 
-0.14131415 -0.20145971 -0.08116859 
MeanDiffCI(explorepro_octo_b3, explorepro_octo_b1)
  meandiff     lwr.ci     upr.ci 
-0.1785616 -0.2336920 -0.1234312 

5.3.1 Graph

pd <- position_dodge(0.4)

ggplot(data=exploreprop_octo_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=sprintf("%.0f", 100*MeanValue), color=Guide), show.legend = FALSE,
            size=4, nudge_x=ifelse(exploreprop_octo_summary$Guide=="Octo", -0.3, 0.3),
            nudge_y=ifelse(exploreprop_octo_summary$Guide=="Octo", -0.05, 0.05)
  )+
  scale_y_continuous(labels = function(x) paste0(x*100),breaks = seq(0,1,0.25))+
  # scale_y_continuous(labels = label_percent(), breaks = seq(0,1,0.25))+
  expand_limits(y=c(0,1))+
  labs(x="Block", y="Usage Rate (%)")+
  scale_x_discrete(labels=c("B1-Train", "B2-Train", "B3-Train"))+
  scale_color_manual(values = c("#d35400", "#95a5a6"))+
  facet_grid(scales = "free", space = "free")+
  theme_bw(base_size = 12)+
  theme(panel.border = element_blank(),
        axis.line = element_line(color = 'grey'),
        legend.position = "none",
        axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 12),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

5.3.2 Assumptions

Shapiro test p < 0.05. The distribution of the residuals is not normal.

m = aov(Proportion ~ Block + Error(Participant), data = exploreprop_octo_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.90988, p-value = 0.03505
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.3.3 Data Transformation

Shapiro test p > 0.05. The distribution of the residuals is now normal.

exploreprop_octo_p_summary$TransVal = sqrt(exploreprop_octo_p_summary$Proportion)
m = aov(TransVal ~ Block + Error(Participant), data = exploreprop_octo_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.96125, p-value = 0.464
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.3.4 ANOVA

ezANOVA(
  exploreprop_octo_p_summary,
  dv = TransVal,
  wid = Participant,
  within = c(Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

5.3.5 Pairwise Comparison

pairwise.t.test(exploreprop_octo_p_summary$TransVal, 
                exploreprop_octo_p_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  exploreprop_octo_p_summary$TransVal and exploreprop_octo_p_summary$Block 

   B1      B2     
B2 0.00168 -      
B3 0.00015 0.36135

P value adjustment method: bonferroni 

5.4 Explore Duration

modedtime_p_summary <- trials %>%
  filter(Mode == "Novice", Phase == "Training" & Result == TRUE & IsOutlier == FALSE) %>%
  group_by(Participant, Guide, Phase, Block) %>%
  summarize(MeanIdle = mean(IdleDuration), MeanGrip = mean(GripDuration), MeanTrigger = mean(TriggerDuration), .groups="drop")

# because P4 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P4", "Sheet", "Training", "B3", 2.5109465, 7.72282145, 1.968268)
modedtime_p_summary = rbind(modedtime_p_summary, newRow)
# because P11 has zero novice trial in B3, we averaged values between that of B1 and B2
newRow = c("P11", "Sheet", "Training", "B3", 3.3913335, 4.0635, 1.73475)
# merge new row into table
modedtime_p_summary = rbind(modedtime_p_summary, newRow)
# # convert from character to numbers
modedtime_p_summary$MeanIdle <- as.numeric(as.character(modedtime_p_summary$MeanIdle))
modedtime_p_summary$MeanGrip <- as.numeric(as.character(modedtime_p_summary$MeanGrip))
modedtime_p_summary$MeanTrigger <- as.numeric(as.character(modedtime_p_summary$MeanTrigger))

modedtime_p_summary

idletime_summary <- modedtime_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(MeanIdle), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
idletime_summary

griptime_summary <- modedtime_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(MeanGrip), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
griptime_summary

triggertime_summary <- modedtime_p_summary %>%
  group_by(Guide, Phase, Block) %>%
  summarize(summary_with_ci(MeanTrigger), .groups="drop") %>%
  mutate(LowerValue = if_else(LowerValue < 0, 0, LowerValue))
triggertime_summary

5.4.1 Graph

pd <- position_dodge(0.4)

ggplot(data=griptime_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(linetype=Guide, color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=format(round(MeanValue,3),nsmall=3), color=Guide),
            size=4, nudge_x=ifelse(griptime_summary$Guide=="Octo", -0.35, 0.35),
            nudge_y=ifelse(griptime_summary$Guide=="Octo", -0.4, 0.4)
  )+
  expand_limits(y=c(0,6))+
  labs(x="Block", y="Explore Duration (s)")+
  facet_grid(~Phase, scales = "free", space = "free")+
  theme(legend.position = "none",
        #legend.position = c(0.85, 0.85), legend.direction = "vertical",
        axis.text.x = element_text(size = 10), axis.text.y = element_text(size = 10),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

5.4.2 Assumptions

Shapiro test p < 0.05. The distribution of the residuals is not normal.

m = aov(MeanGrip ~ Block*Guide + Error(Participant), data = modedtime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.9576, p-value = 0.03595
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.4.3 Data Transformation

Shapiro test p > 0.05. The distribution of the residuals is now normal.

modedtime_p_summary$TransVal = sqrt(modedtime_p_summary$MeanGrip)
m = aov(TransVal ~ Block*Guide + Error(Participant), data = modedtime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.9653, p-value = 0.08566
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.4.4 ANOVA

ezANOVA(
  modedtime_p_summary,
  dv = sqrt(MeanGrip),
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

5.4.5 Pairwise Comparison

pairwise.t.test(sqrt(modedtime_p_summary$MeanGrip), 
                modedtime_p_summary$Block, 
                paired=TRUE, 
                p.adj="bonf")

    Pairwise comparisons using paired t tests 

data:  sqrt(modedtime_p_summary$MeanGrip) and modedtime_p_summary$Block 

   B1     B2    
B2 0.0046 -     
B3 0.0807 1.0000

P value adjustment method: bonferroni 

5.5 Draw Duration

5.5.1 Graph

pd <- position_dodge(0.4)

ggplot(data=triggertime_summary, aes(x=Block, y=MeanValue, group=Guide)) +
  geom_errorbar(aes(ymin=LowerValue, ymax=UpperValue), width=.3, position=pd) +
  geom_line(aes(linetype=Guide, color=Guide), position=pd)+
  geom_point(aes(color=Guide, shape=Guide), size=3, position=pd)+
  geom_text(aes(label=format(round(MeanValue,3),nsmall=3), color=Guide),
            size=4, nudge_x=ifelse(triggertime_summary$Guide=="Octo", -0.35, 0.35),
            nudge_y=ifelse(triggertime_summary$Guide=="Octo", -0.4, 0.4)
  )+
  expand_limits(y=c(0,6))+
  labs(x="Block", y="Draw Duration (s)")+
  facet_grid(~Phase, scales = "free", space = "free")+
  theme(legend.position = c(0.85, 0.15), legend.direction = "vertical",
        axis.text.x = element_text(size = 10), axis.text.y = element_text(size = 10),
        axis.title.y = element_text(margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.title.x = element_text(margin = margin(t = 5, r = 0, b = 0, l = 0)))

5.5.2 Assumptions

Shapiro test p > 0.05. The distribution of the residuals is normal.

m = aov(MeanTrigger ~ Block*Guide + Error(Participant), data = modedtime_p_summary)
shapiro.test(residuals(m$Within))

    Shapiro-Wilk normality test

data:  residuals(m$Within)
W = 0.97384, p-value = 0.2239
plotNormalHistogram(residuals(m$Within))

qqnorm(residuals(m$Within)); qqline(residuals(m$Within))

5.5.3 ANOVA

ezANOVA(
  modedtime_p_summary,
  dv = MeanTrigger,
  wid = Participant,
  within = c(Guide, Block)
)
$ANOVA

$`Mauchly's Test for Sphericity`

$`Sphericity Corrections`
NA

6 SUBJECTIVE RATING

ratingParticipant <- read_csv("./data2.csv")
Parsed with column specification:
cols(
  Participant = col_character(),
  Gender = col_character(),
  Age = col_double(),
  Guide = col_character(),
  Easy = col_double(),
  Fast = col_double(),
  Accurate = col_double(),
  Comfortable = col_double(),
  RememberMany = col_double()
)
ratingCount <- read_csv("./data3.csv")
Parsed with column specification:
cols(
  Question = col_character(),
  Guide = col_character(),
  `Strongly Disagree` = col_double(),
  Disagree = col_double(),
  `Slightly Disagree` = col_double(),
  Neutral = col_double(),
  `Slightly Agree` = col_double(),
  Agree = col_double(),
  `Strongly Agree` = col_double()
)
overall <- read_csv("./data4.csv")
Parsed with column specification:
cols(
  Participant = col_character(),
  Gender = col_character(),
  Age = col_double(),
  Overall = col_character(),
  Frequency = col_character()
)
length(unique(overall$Participant))
[1] 12
ratingParticipant

names(ratingCount)[3] <- "Strongly\nDisagree"
names(ratingCount)[5] <- "Slightly\nDisagree"
names(ratingCount)[7] <- "Slightly\nAgree"
names(ratingCount)[9] <- "Strongly\nAgree"
ratingCount

likert(Question ~ .| Guide, data=ratingCount, layout=c(1,2),
       scales=list(y=list(relation="free")),between=list(y=2.5),
       strip.left=FALSE, strip=FALSE,
       par.strip.text=list(cex=1, lines=2), ylab=NULL, cex=1.2,
       xlim=c(-100,-50, -25, 0, 25, 50, 75, 100),
       ReferenceZero=4, as.percent="noRightAxis",
       reference.line.col="black",
       col=c("#D31819", "#FF792E", "#FFAE73", "#DED9D9", "#74AED5", "#3881B8", "#0E529F"),
       borders = list(),
       positive.order=FALSE,
       main = list(""),
       xlab="Proportion (%)",
       auto.key=list(space="bottom", rows=1, reverse=FALSE, padding.text=1,
                     rect= list(col=c("#D31819", "#FF792E", "#FFAE73", "#DED9D9", "#74AED5", "#3881B8", "#0E529F"), # <- Specify colors again (for keys)
                    border = "black")))


# export to pdf: 4.0 x 8.5 inch
ratingParticipantLong = pivot_longer(ratingParticipant, cols = 5:9, names_to = "Question", values_to = "Rating")
ratingParticipantLong

wilcox <- ratingParticipantLong %>%
  group_by(Question) %>%
  wilcox_test(Rating ~ Guide, paired=TRUE) %>%
  add_significance("p")
wilcox
LS0tCnRpdGxlOiAiT2N0b1BvY3VzIGluIFZSIC0gUmVzdWx0IEFuYWx5c2lzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0aGVtZTogbHVtZW4KICAgIGhpZ2hsaWdodDogZGVmYXVsdAogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBudW1iZXJfc2VjdGlvbnM6IFRSVUUKLS0tCgojIFRvb2xzICYgTGlicmFyaWVzCgpgYGB7cn0KbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoZXopCmxpYnJhcnkoTUFTUykKbGlicmFyeShlZmZzaXplKQpsaWJyYXJ5KHJjb21wYW5pb24pCmxpYnJhcnkoQVJUb29sKQpsaWJyYXJ5KGVtbWVhbnMpCmxpYnJhcnkoSEgpCmxpYnJhcnkocnN0YXRpeCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoRGVzY1Rvb2xzKQoKCm5vcm1hbF9lcnJvciA8LSBmdW5jdGlvbihkKSB7CiAgbiA8LSBsZW5ndGgoZCkKICBxbm9ybSgwLjk3NSkgKiAoc2QoZCkgL3NxcnQobikpCn0KCnN1bW1hcnlfd2l0aF9jaSA8LSBmdW5jdGlvbihkKSB7CiAgdGliYmxlKAogICAgTWVhblZhbHVlID0gbWVhbihkKSwKICAgIEVycm9yVmFsdWUgPSBub3JtYWxfZXJyb3IoZCksCiAgICBMb3dlclZhbHVlID0gTWVhblZhbHVlIC0gRXJyb3JWYWx1ZSwKICAgIFVwcGVyVmFsdWUgPSBNZWFuVmFsdWUgKyBFcnJvclZhbHVlCiAgKQp9CmBgYAojIExvYWQgZGF0YQoKYGBge3J9CnRyaWFscyA8LSByZWFkX2NzdigKICAiLi9kYXRhMS5jc3YiLAogIGNvbF90eXBlcyA9IGNvbHMoCiAgICBQYXJ0aWNpcGFudCA9IGNvbF9mYWN0b3IoKSwKICAgIEd1aWRlID0gY29sX2ZhY3RvcigpLAogICAgU2V0ID0gY29sX2ZhY3RvcigpLAogICAgUGhhc2UgPSBjb2xfZmFjdG9yKCksCiAgICBCbG9jayA9IGNvbF9mYWN0b3IoKSwKICAgIFRyaWFsID0gY29sX2NoYXJhY3RlcigpLAogICAgVHJpYWxOYW1lID0gY29sX2ZhY3RvcigpLAogICAgVHJpZ2dlcmVkTmFtZSA9IGNvbF9mYWN0b3IoKSwKICAgIFJlc3VsdCA9IGNvbF9sb2dpY2FsKCksCiAgICBNb2RlID0gY29sX2ZhY3RvcigpLAogICAgUmVzdGFydENvdW50ID0gY29sX2RvdWJsZSgpLAogICAgRHJhd1RpbWUgPSBjb2xfZG91YmxlKCksCiAgICBOb3ZpY2VUaW1lID0gY29sX2RvdWJsZSgpLAogICAgRW5kVGltZSA9IGNvbF9kb3VibGUoKSwKICAgIFRyaWdnZXJEdXJhdGlvbiA9IGNvbF9kb3VibGUoKSwKICAgIEdyaXBEdXJhdGlvbiA9IGNvbF9kb3VibGUoKSwKICAgIElkbGVEdXJhdGlvbiA9IGNvbF9kb3VibGUoKQogICkKKSAlPiUKICBmaWx0ZXIoUGFydGljaXBhbnQgIT0gIlAzIiAmIFBhcnRpY2lwYW50ICE9ICJQNiIpICU+JQogIG11dGF0ZSgKICAgIFBhcnRpY2lwYW50ID0gZHJvcGxldmVscyhQYXJ0aWNpcGFudCksCiAgICBCbG9jayA9IGZhY3RvcihCbG9jayksCiAgICBJbnB1dFRpbWUgPSBFbmRUaW1lLU5vdmljZVRpbWUsCiAgICBJc091dGxpZXIgPSBQaGFzZSA9PSAiVHJhaW5pbmciICYKICAgICAgICAgICBFbmRUaW1lID4gbWVhbihFbmRUaW1lW1BoYXNlID09ICJUcmFpbmluZyJdKSArIDMgKiBzZChFbmRUaW1lW1BoYXNlID09ICJUcmFpbmluZyJdKSkKCnRyaWFscwoKIyBOdW1iZXIgb2Ygb3V0bGllcnMKYSA9IHN1bSh0cmlhbHMkSXNPdXRsaWVyID09IFRSVUUpCmIgPSBzdW0odHJpYWxzJFBoYXNlID09ICJUcmFpbmluZyIpCihhL2IpKjEwMAoKYGBgCgojIFRJTUUKCiMjIFRyaWFsIFRpbWUKYGBge3J9CnRyaWFsdGltZV9wX3N1bW1hcnkgPC0gdHJpYWxzICU+JQogIGZpbHRlcihNb2RlID09ICJOb3ZpY2UiLCBQaGFzZSA9PSAiVHJhaW5pbmciICYgUmVzdWx0ID09IFRSVUUgJiBJc091dGxpZXIgPT0gRkFMU0UpICU+JQogIGdyb3VwX2J5KFBhcnRpY2lwYW50LCBHdWlkZSwgUGhhc2UsIEJsb2NrKSAlPiUKICBzdW1tYXJpemUoTWVhbiA9IG1lYW4oRW5kVGltZSksIC5ncm91cHM9ImRyb3AiKQoKIyBiZWNhdXNlIFA0IGhhcyB6ZXJvIG5vdmljZSB0cmlhbCBpbiBCMywgd2UgYXZlcmFnZWQgdmFsdWVzIGJldHdlZW4gdGhhdCBvZiBCMSBhbmQgQjIKbmV3Um93ID0gYygiUDQiLCAiU2hlZXQiLCAiVHJhaW5pbmciLCAiQjMiLCAxMi4yMDE5ODIpCnRyaWFsdGltZV9wX3N1bW1hcnkgPSByYmluZCh0cmlhbHRpbWVfcF9zdW1tYXJ5LCBuZXdSb3cpCiMgYmVjYXVzZSBQMTEgaGFzIHplcm8gbm92aWNlIHRyaWFsIGluIEIzLCB3ZSBhdmVyYWdlZCB2YWx1ZXMgYmV0d2VlbiB0aGF0IG9mIEIxIGFuZCBCMgpuZXdSb3cgPSBjKCJQMTEiLCAiU2hlZXQiLCAiVHJhaW5pbmciLCAiQjMiLCA5LjE4OTU4MzUpCiMgbWVyZ2UgbmV3IHJvdyBpbnRvIHRhYmxlCnRyaWFsdGltZV9wX3N1bW1hcnkgPSByYmluZCh0cmlhbHRpbWVfcF9zdW1tYXJ5LCBuZXdSb3cpCiMgY29udmVydCBmcm9tIGNoYXJhY3RlciB0byBudW1iZXJzCnRyaWFsdGltZV9wX3N1bW1hcnkkTWVhbiA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0cmlhbHRpbWVfcF9zdW1tYXJ5JE1lYW4pKQp0cmlhbHRpbWVfcF9zdW1tYXJ5Cgp0cmlhbHRpbWVfb2N0byA8LSBzdWJzZXQodHJpYWx0aW1lX3Bfc3VtbWFyeSwgIEd1aWRlID09ICJPY3RvIiwgTWVhbiwgZHJvcCA9IFRSVUUpCnRyaWFsdGltZV9zaGVldCA8LSBzdWJzZXQodHJpYWx0aW1lX3Bfc3VtbWFyeSwgIEd1aWRlID09ICJTaGVldCIsIE1lYW4sIGRyb3AgPSBUUlVFKQpNZWFuRGlmZkNJKHRyaWFsdGltZV9zaGVldCwgdHJpYWx0aW1lX29jdG8pCgp0cmlhbHRpbWVfYjEgPC0gc3Vic2V0KHRyaWFsdGltZV9wX3N1bW1hcnksICBCbG9jayA9PSAiQjEiLCBNZWFuLCBkcm9wID0gVFJVRSkKdHJpYWx0aW1lX2IyIDwtIHN1YnNldCh0cmlhbHRpbWVfcF9zdW1tYXJ5LCAgQmxvY2sgPT0gIkIyIiwgTWVhbiwgZHJvcCA9IFRSVUUpCnRyaWFsdGltZV9iMyA8LSBzdWJzZXQodHJpYWx0aW1lX3Bfc3VtbWFyeSwgIEJsb2NrID09ICJCMyIsIE1lYW4sIGRyb3AgPSBUUlVFKQpNZWFuRGlmZkNJKHRyaWFsdGltZV9iMiwgdHJpYWx0aW1lX2IxKQpNZWFuRGlmZkNJKHRyaWFsdGltZV9iMywgdHJpYWx0aW1lX2IxKQoKdHJpYWx0aW1lX3N1bW1hcnkgPC0gdHJpYWx0aW1lX3Bfc3VtbWFyeSAlPiUKICBncm91cF9ieShHdWlkZSwgUGhhc2UsIEJsb2NrKSAlPiUKICBzdW1tYXJpemUoc3VtbWFyeV93aXRoX2NpKE1lYW4pLCAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgbXV0YXRlKExvd2VyVmFsdWUgPSBpZl9lbHNlKExvd2VyVmFsdWUgPCAwLCAwLCBMb3dlclZhbHVlKSkKdHJpYWx0aW1lX3N1bW1hcnkKYGBgCgojIyMgR3JhcGgKCmBgYHtyfQpwZCA8LSBwb3NpdGlvbl9kb2RnZSgwLjQpCgpnZ3Bsb3QoZGF0YT10cmlhbHRpbWVfc3VtbWFyeSwgYWVzKHg9QmxvY2ssIHk9TWVhblZhbHVlLCBncm91cD1HdWlkZSkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPUxvd2VyVmFsdWUsIHltYXg9VXBwZXJWYWx1ZSksIHdpZHRoPS4zLCBwb3NpdGlvbj1wZCkgKwogIGdlb21fbGluZShhZXMoY29sb3I9R3VpZGUpLCBwb3NpdGlvbj1wZCkrCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9R3VpZGUsIHNoYXBlPUd1aWRlKSwgc2l6ZT0zLCBwb3NpdGlvbj1wZCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1mb3JtYXQocm91bmQoTWVhblZhbHVlLDEpLG5zbWFsbD0xKSwgY29sb3I9R3VpZGUpLCBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgICBzaXplPTQsIG51ZGdlX3g9aWZlbHNlKHRyaWFsdGltZV9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjMsIDAuMyksCiAgICAgICAgICAgIG51ZGdlX3k9aWZlbHNlKHRyaWFsdGltZV9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjQsIDAuNCkKICApKwogIGV4cGFuZF9saW1pdHMoeT1jKDAsMTEuNSkpKwogIGxhYnMoeD0iQmxvY2siLCB5PSJUaW1lIChzKSIpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkIxLVRyYWluIiwgIkIyLVRyYWluIiwgIkIzLVRyYWluIikpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjZDM1NDAwIiwgIiM5NWE1YTYiKSxsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIHNjYWxlX3NoYXBlX2Rpc2NyZXRlKGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgc2NhbGVfbGluZXR5cGUobGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBmYWNldF9ncmlkKHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIpKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjEpLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMCwgciA9IDUsIGIgPSAwLCBsID0gMCkpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDUsIHIgPSAwLCBiID0gMCwgbCA9IDApKSkKYGBgCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPCAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm90IG5vcm1hbC4KCmBgYHtyfQptID0gYW92KE1lYW4gfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IHRyaWFsdGltZV9wX3N1bW1hcnkpCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobSRXaXRoaW4pKQpwbG90Tm9ybWFsSGlzdG9ncmFtKHJlc2lkdWFscyhtJFdpdGhpbikpCnFxbm9ybShyZXNpZHVhbHMobSRXaXRoaW4pKTsgcXFsaW5lKHJlc2lkdWFscyhtJFdpdGhpbikpCmBgYAoKIyMjIERhdGEgVHJhbnNmb3JtYXRpb24KU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm93IG5vcm1hbC4KCmBgYHtyfQp0cmlhbHRpbWVfcF9zdW1tYXJ5JFRyYW5zVmFsID0gbG9nKHRyaWFsdGltZV9wX3N1bW1hcnkkTWVhbikKbSA9IGFvdihUcmFuc1ZhbCB+IEJsb2NrKkd1aWRlICsgRXJyb3IoUGFydGljaXBhbnQpLCBkYXRhID0gdHJpYWx0aW1lX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgQU5PVkEKCmBgYHtyfQplekFOT1ZBKAogIHRyaWFsdGltZV9wX3N1bW1hcnksCiAgZHYgPSBsb2coTWVhbiksCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KHRyaWFsdGltZV9wX3N1bW1hcnkkVHJhbnNWYWwsIAogICAgICAgICAgICAgICAgdHJpYWx0aW1lX3Bfc3VtbWFyeSRCbG9jaywgCiAgICAgICAgICAgICAgICBwYWlyZWQ9VFJVRSwgCiAgICAgICAgICAgICAgICBwLmFkaj0iYm9uZiIpCmBgYAoKIyMgUmVhY3Rpb24gVGltZQpgYGB7cn0KcmVhY3Rpb250aW1lX3Bfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKE1vZGUgPT0gIk5vdmljZSIgJiBQaGFzZSA9PSAiVHJhaW5pbmciICYgUmVzdWx0ID09IFRSVUUgJiBJc091dGxpZXIgPT0gRkFMU0UpICU+JQogIGdyb3VwX2J5KFBhcnRpY2lwYW50LCBHdWlkZSwgUGhhc2UsIEJsb2NrKSAlPiUKICBzdW1tYXJpemUoTWVhbiA9IG1lYW4oTm92aWNlVGltZSksIC5ncm91cHM9ImRyb3AiKQoKIyBiZWNhdXNlIFA0IGhhcyB6ZXJvIG5vdmljZSB0cmlhbCBpbiBCMywgd2UgYXZlcmFnZWQgdmFsdWVzIGJldHdlZW4gdGhhdCBvZiBCMSBhbmQgQjIKbmV3Um93ID0gYygiUDQiLCAiU2hlZXQiLCAiVHJhaW5pbmciLCAiQjMiLCAwLjkzNzMwMzU1KQpyZWFjdGlvbnRpbWVfcF9zdW1tYXJ5ID0gcmJpbmQocmVhY3Rpb250aW1lX3Bfc3VtbWFyeSwgbmV3Um93KQojIGJlY2F1c2UgUDExIGhhcyB6ZXJvIG5vdmljZSB0cmlhbCBpbiBCMywgd2UgYXZlcmFnZWQgdmFsdWVzIGJldHdlZW4gdGhhdCBvZiBCMSBhbmQgQjIKbmV3Um93ID0gYygiUDExIiwgIlNoZWV0IiwgIlRyYWluaW5nIiwgIkIzIiwgMS40ODM1ODMzNSkKIyBtZXJnZSBuZXcgcm93IGludG8gdGFibGUKcmVhY3Rpb250aW1lX3Bfc3VtbWFyeSA9IHJiaW5kKHJlYWN0aW9udGltZV9wX3N1bW1hcnksIG5ld1JvdykKIyBjb252ZXJ0IGZyb20gY2hhcmFjdGVyIHRvIG51bWJlcnMKcmVhY3Rpb250aW1lX3Bfc3VtbWFyeSRNZWFuIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHJlYWN0aW9udGltZV9wX3N1bW1hcnkkTWVhbikpCnJlYWN0aW9udGltZV9wX3N1bW1hcnkKCnJlYWN0aW9udGltZV9vY3RvIDwtIHN1YnNldChyZWFjdGlvbnRpbWVfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIk9jdG8iLCBNZWFuLCBkcm9wID0gVFJVRSkKcmVhY3Rpb250aW1lX3NoZWV0IDwtIHN1YnNldChyZWFjdGlvbnRpbWVfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIlNoZWV0IiwgTWVhbiwgZHJvcCA9IFRSVUUpCk1lYW5EaWZmQ0kocmVhY3Rpb250aW1lX3NoZWV0LCByZWFjdGlvbnRpbWVfb2N0bykKCnJlYWN0aW9udGltZV9zdW1tYXJ5IDwtIHJlYWN0aW9udGltZV9wX3N1bW1hcnkgJT4lCiAgZ3JvdXBfYnkoR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKHN1bW1hcnlfd2l0aF9jaShNZWFuKSwgLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShMb3dlclZhbHVlID0gaWZfZWxzZShMb3dlclZhbHVlIDwgMCwgMCwgTG93ZXJWYWx1ZSkpCnJlYWN0aW9udGltZV9zdW1tYXJ5CmBgYAoKIyMjIEdyYXBoCgpgYGB7cn0KcGQgPC0gcG9zaXRpb25fZG9kZ2UoMC40KQoKZ2dwbG90KGRhdGE9cmVhY3Rpb250aW1lX3N1bW1hcnksIGFlcyh4PUJsb2NrLCB5PU1lYW5WYWx1ZSwgZ3JvdXA9R3VpZGUpKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1Mb3dlclZhbHVlLCB5bWF4PVVwcGVyVmFsdWUpLCB3aWR0aD0uMywgcG9zaXRpb249cGQpICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yPUd1aWRlKSwgcG9zaXRpb249cGQpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPUd1aWRlLCBzaGFwZT1HdWlkZSksIHNpemU9MywgcG9zaXRpb249cGQpKwogIGdlb21fdGV4dChhZXMobGFiZWw9Zm9ybWF0KHJvdW5kKE1lYW5WYWx1ZSwxKSxuc21hbGw9MSksIGNvbG9yPUd1aWRlKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgICAgc2l6ZT00LCBudWRnZV94PWlmZWxzZShyZWFjdGlvbnRpbWVfc3VtbWFyeSRHdWlkZT09Ik9jdG8iLCAtMC4xLCAwLjEpLAogICAgICAgICAgICBudWRnZV95PWlmZWxzZShyZWFjdGlvbnRpbWVfc3VtbWFyeSRHdWlkZT09Ik9jdG8iLCAwLjgsIC0wLjgpCiAgKSsKICBleHBhbmRfbGltaXRzKHk9YygwLDExLjUpKSsKICBsYWJzKHg9IkJsb2NrIiwgeT0iVGltZSAocykiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJCMS1UcmFpbiIsICJCMi1UcmFpbiIsICJCMy1UcmFpbiIpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI2QzNTQwMCIsICIjOTVhNWE2IikpKwogICMgZmFjZXRfZ3JpZChzY2FsZXMgPSAiZnJlZSIsIHNwYWNlID0gImZyZWUiKSsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikrCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICdncmV5JyksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICMgbGVnZW5kLnBvc2l0aW9uID0gYygwLjgsIDAuODUpLCBsZWdlbmQuZGlyZWN0aW9uID0gInZlcnRpY2FsIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDAsIHIgPSA1LCBiID0gMCwgbCA9IDApKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSA1LCByID0gMCwgYiA9IDAsIGwgPSAwKSkpCmBgYAoKIyMjIEFzc3VtcHRpb25zClNoYXBpcm8gdGVzdCBwID4gMC4wNS4gVGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzIGlzIG5vcm1hbC4KCmBgYHtyfQptID0gYW92KE1lYW4gfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IHJlYWN0aW9udGltZV9wX3N1bW1hcnkpCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobSRXaXRoaW4pKQpwbG90Tm9ybWFsSGlzdG9ncmFtKHJlc2lkdWFscyhtJFdpdGhpbikpCnFxbm9ybShyZXNpZHVhbHMobSRXaXRoaW4pKTsgcXFsaW5lKHJlc2lkdWFscyhtJFdpdGhpbikpCmBgYAojIyMgQU5PVkEKCmBgYHtyfQplekFOT1ZBKAogIHJlYWN0aW9udGltZV9wX3N1bW1hcnksCiAgZHYgPSBNZWFuLAogIHdpZCA9IFBhcnRpY2lwYW50LAogIHdpdGhpbiA9IGMoR3VpZGUsIEJsb2NrKQopCmBgYAoKIyMgSW5wdXQgVGltZQpgYGB7cn0KaW5wdXR0aW1lX3Bfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKE1vZGUgPT0gIk5vdmljZSIsIFBoYXNlID09ICJUcmFpbmluZyIgJiBSZXN1bHQgPT0gVFJVRSAmIElzT3V0bGllciA9PSBGQUxTRSkgJT4lCiAgZ3JvdXBfYnkoUGFydGljaXBhbnQsIEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShNZWFuID0gbWVhbihJbnB1dFRpbWUpLCAuZ3JvdXBzPSJkcm9wIikKCiMgYmVjYXVzZSBQNCBoYXMgemVybyBub3ZpY2UgdHJpYWwgaW4gQjMsIHdlIGF2ZXJhZ2VkIHZhbHVlcyBiZXR3ZWVuIHRoYXQgb2YgQjEgYW5kIEIyCm5ld1JvdyA9IGMoIlA0IiwgIlNoZWV0IiwgIlRyYWluaW5nIiwgIkIzIiwgMTEuMjY0Njc4NSkKaW5wdXR0aW1lX3Bfc3VtbWFyeSA9IHJiaW5kKGlucHV0dGltZV9wX3N1bW1hcnksIG5ld1JvdykKIyBiZWNhdXNlIFAxMSBoYXMgemVybyBub3ZpY2UgdHJpYWwgaW4gQjMsIHdlIGF2ZXJhZ2VkIHZhbHVlcyBiZXR3ZWVuIHRoYXQgb2YgQjEgYW5kIEIyCm5ld1JvdyA9IGMoIlAxMSIsICJTaGVldCIsICJUcmFpbmluZyIsICJCMyIsIDcuNzA2KQojIG1lcmdlIG5ldyByb3cgaW50byB0YWJsZQppbnB1dHRpbWVfcF9zdW1tYXJ5ID0gcmJpbmQoaW5wdXR0aW1lX3Bfc3VtbWFyeSwgbmV3Um93KQojIGNvbnZlcnQgZnJvbSBjaGFyYWN0ZXIgdG8gbnVtYmVycwppbnB1dHRpbWVfcF9zdW1tYXJ5JE1lYW4gPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoaW5wdXR0aW1lX3Bfc3VtbWFyeSRNZWFuKSkKaW5wdXR0aW1lX3Bfc3VtbWFyeQoKaW5wdXR0aW1lX29jdG8gPC0gc3Vic2V0KGlucHV0dGltZV9wX3N1bW1hcnksICBHdWlkZSA9PSAiT2N0byIsIE1lYW4sIGRyb3AgPSBUUlVFKQppbnB1dHRpbWVfc2hlZXQgPC0gc3Vic2V0KGlucHV0dGltZV9wX3N1bW1hcnksICBHdWlkZSA9PSAiU2hlZXQiLCBNZWFuLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShpbnB1dHRpbWVfc2hlZXQsIGlucHV0dGltZV9vY3RvKQoKaW5wdXR0aW1lX2IxIDwtIHN1YnNldChpbnB1dHRpbWVfcF9zdW1tYXJ5LCAgQmxvY2sgPT0gIkIxIiwgTWVhbiwgZHJvcCA9IFRSVUUpCmlucHV0dGltZV9iMiA8LSBzdWJzZXQoaW5wdXR0aW1lX3Bfc3VtbWFyeSwgIEJsb2NrID09ICJCMiIsIE1lYW4sIGRyb3AgPSBUUlVFKQppbnB1dHRpbWVfYjMgPC0gc3Vic2V0KGlucHV0dGltZV9wX3N1bW1hcnksICBCbG9jayA9PSAiQjMiLCBNZWFuLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShpbnB1dHRpbWVfYjIsIGlucHV0dGltZV9iMSkKTWVhbkRpZmZDSShpbnB1dHRpbWVfYjMsIGlucHV0dGltZV9iMSkKCmlucHV0dGltZV9zdW1tYXJ5IDwtIGlucHV0dGltZV9wX3N1bW1hcnkgJT4lCiAgZ3JvdXBfYnkoR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKHN1bW1hcnlfd2l0aF9jaShNZWFuKSwgLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShMb3dlclZhbHVlID0gaWZfZWxzZShMb3dlclZhbHVlIDwgMCwgMCwgTG93ZXJWYWx1ZSkpCmlucHV0dGltZV9zdW1tYXJ5CgpgYGAKCiMjIyBHcmFwaAoKYGBge3J9CnBkIDwtIHBvc2l0aW9uX2RvZGdlKDAuNCkKCmdncGxvdChkYXRhPWlucHV0dGltZV9zdW1tYXJ5LCBhZXMoeD1CbG9jaywgeT1NZWFuVmFsdWUsIGdyb3VwPUd1aWRlKSkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49TG93ZXJWYWx1ZSwgeW1heD1VcHBlclZhbHVlKSwgd2lkdGg9LjMsIHBvc2l0aW9uPXBkKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1HdWlkZSksIHBvc2l0aW9uPXBkKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1HdWlkZSwgc2hhcGU9R3VpZGUpLCBzaXplPTMsIHBvc2l0aW9uPXBkKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPWZvcm1hdChyb3VuZChNZWFuVmFsdWUsMSksbnNtYWxsPTEpLCBjb2xvcj1HdWlkZSksIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICAgIHNpemU9NCwgbnVkZ2VfeD1pZmVsc2UoaW5wdXR0aW1lX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgLTAuMywgMC4zKSwKICAgICAgICAgICAgbnVkZ2VfeT1pZmVsc2UoaW5wdXR0aW1lX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgLTAuNCwgMC40KQogICkrCiAgZXhwYW5kX2xpbWl0cyh5PWMoMCwxMS41KSkrCiAgbGFicyh4PSJCbG9jayIsIHk9IlRpbWUgKHMpIikrCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiQjEtVHJhaW4iLCAiQjItVHJhaW4iLCAiQjMtVHJhaW4iKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiNkMzU0MDAiLCAiIzk1YTVhNiIpKSsKICAjIGZhY2V0X2dyaWQoc2NhbGVzID0gImZyZWUiLCBzcGFjZSA9ICJmcmVlIikrCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAjbGVnZW5kLnBvc2l0aW9uID0gYygwLjgsIDAuMTUpLCBsZWdlbmQuZGlyZWN0aW9uID0gInZlcnRpY2FsIiwKICAgICAgICAjIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMCwgciA9IDUsIGIgPSAwLCBsID0gMCkpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDUsIHIgPSAwLCBiID0gMCwgbCA9IDApKSkKYGBgCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPCAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm90IG5vcm1hbC4KCmBgYHtyfQptID0gYW92KE1lYW4gfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IGlucHV0dGltZV9wX3N1bW1hcnkpCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobSRXaXRoaW4pKQpwbG90Tm9ybWFsSGlzdG9ncmFtKHJlc2lkdWFscyhtJFdpdGhpbikpCnFxbm9ybShyZXNpZHVhbHMobSRXaXRoaW4pKTsgcXFsaW5lKHJlc2lkdWFscyhtJFdpdGhpbikpCmBgYAoKIyMjIERhdGEgVHJhbnNmb3JtYXRpb24KU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm93IG5vcm1hbC4KCmBgYHtyfQppbnB1dHRpbWVfcF9zdW1tYXJ5JFRyYW5zVmFsID0gc3FydChpbnB1dHRpbWVfcF9zdW1tYXJ5JE1lYW4pCm0gPSBhb3YoVHJhbnNWYWwgfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IGlucHV0dGltZV9wX3N1bW1hcnkpCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobSRXaXRoaW4pKQpwbG90Tm9ybWFsSGlzdG9ncmFtKHJlc2lkdWFscyhtJFdpdGhpbikpCnFxbm9ybShyZXNpZHVhbHMobSRXaXRoaW4pKTsgcXFsaW5lKHJlc2lkdWFscyhtJFdpdGhpbikpCmBgYAoKIyMjIEFOT1ZBCgpgYGB7cn0KZXpBTk9WQSgKICBpbnB1dHRpbWVfcF9zdW1tYXJ5LAogIGR2ID0gVHJhbnNWYWwsCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KGlucHV0dGltZV9wX3N1bW1hcnkkVHJhbnNWYWwsIAogICAgICAgICAgICAgICAgaW5wdXR0aW1lX3Bfc3VtbWFyeSRCbG9jaywgCiAgICAgICAgICAgICAgICBwYWlyZWQ9VFJVRSwgCiAgICAgICAgICAgICAgICBwLmFkaj0iYm9uZiIpCmBgYAoKCgojIEFDQ1VSQUNZCgojIyBPdmVyYWxsIFRyYWluaW5nCmBgYHtyfQphY2N1cmFjeV9vdmVyYWxsdHJhaW5pbmdfcF9zdW1tYXJ5IDwtIHRyaWFscyAlPiUKICBmaWx0ZXIoUGhhc2UgPT0gIlRyYWluaW5nIiAmICFJc091dGxpZXIpICU+JQogIGdyb3VwX2J5KFBhcnRpY2lwYW50LCBHdWlkZSwgUGhhc2UsIEJsb2NrKSAlPiUKICBzdW1tYXJpemUoTWVhbiA9IG1lYW4oUmVzdWx0KSwgLmdyb3Vwcz0iZHJvcCIpCmFjY3VyYWN5X292ZXJhbGx0cmFpbmluZ19wX3N1bW1hcnkKCm92ZXJhbGx0cmFpbmluZ2FjY19vY3RvIDwtIHN1YnNldChhY2N1cmFjeV9vdmVyYWxsdHJhaW5pbmdfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIk9jdG8iLCBNZWFuLCBkcm9wID0gVFJVRSkKb3ZlcmFsbHRyYWluaW5nYWNjX3NoZWV0IDwtIHN1YnNldChhY2N1cmFjeV9vdmVyYWxsdHJhaW5pbmdfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIlNoZWV0IiwgTWVhbiwgZHJvcCA9IFRSVUUpCk1lYW5EaWZmQ0kob3ZlcmFsbHRyYWluaW5nYWNjX3NoZWV0LCBvdmVyYWxsdHJhaW5pbmdhY2Nfb2N0bykKCmFjY3VyYWN5X292ZXJhbGx0cmFpbmluZ19zdW1tYXJ5IDwtIGFjY3VyYWN5X292ZXJhbGx0cmFpbmluZ19wX3N1bW1hcnkgJT4lCiAgZ3JvdXBfYnkoR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKHN1bW1hcnlfd2l0aF9jaShNZWFuKSwgLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShMb3dlclZhbHVlID0gaWZfZWxzZShMb3dlclZhbHVlIDwgMCwgMCwgTG93ZXJWYWx1ZSkpCgphY2N1cmFjeV9vdmVyYWxsdHJhaW5pbmdfc3VtbWFyeQpgYGAKCiMjIyBHcmFwaAoKYGBge3J9CnBkIDwtIHBvc2l0aW9uX2RvZGdlKDAuNCkKCmdncGxvdChkYXRhPWFjY3VyYWN5X292ZXJhbGx0cmFpbmluZ19zdW1tYXJ5LCBhZXMoeD1CbG9jaywgeT1NZWFuVmFsdWUsIGdyb3VwPUd1aWRlKSkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49TG93ZXJWYWx1ZSwgeW1heD1VcHBlclZhbHVlKSwgd2lkdGg9LjMsIHBvc2l0aW9uPXBkKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1HdWlkZSksIHBvc2l0aW9uPXBkKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1HdWlkZSwgc2hhcGU9R3VpZGUpLCBzaXplPTMsIHBvc2l0aW9uPXBkKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXNwcmludGYoIiUuMGYiLCAxMDAqTWVhblZhbHVlKSwgY29sb3I9R3VpZGUpLCBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgICBzaXplPTQsIG51ZGdlX3g9aWZlbHNlKGFjY3VyYWN5X292ZXJhbGx0cmFpbmluZ19zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjMsIDAuMyksCiAgICAgICAgICAgIG51ZGdlX3k9aWZlbHNlKGFjY3VyYWN5X292ZXJhbGx0cmFpbmluZ19zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIDAuMSwgLTAuMSkKICApKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCoxMDApLGJyZWFrcyA9IHNlcSgwLDEsMC4yNSkpKwogICMgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoKSwgYnJlYWtzID0gc2VxKDAsMSwwLjI1KSkrCiAgZXhwYW5kX2xpbWl0cyh5PWMoMCwxKSkrCiAgbGFicyh4PSJCbG9jayIsIHk9IkFjY3VyYWN5ICglKSIpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkIxLVRyYWluIiwgIkIyLVRyYWluIiwgIkIzLVRyYWluIikpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjZDM1NDAwIiwgIiM5NWE1YTYiKSxsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIHNjYWxlX3NoYXBlX2Rpc2NyZXRlKGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgc2NhbGVfbGluZXR5cGUobGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBmYWNldF9ncmlkKHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIpKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjEpLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMCwgciA9IDUsIGIgPSAwLCBsID0gMCkpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDUsIHIgPSAwLCBiID0gMCwgbCA9IDApKSkKYGBgCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm9ybWFsLgoKYGBge3J9Cm0gPSBhb3YoTWVhbiB+IEJsb2NrKkd1aWRlICsgRXJyb3IoUGFydGljaXBhbnQpLCBkYXRhID0gYWNjdXJhY3lfb3ZlcmFsbHRyYWluaW5nX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgoKIyMjIEFOT1ZBCmBgYHtyfQplekFOT1ZBKAogIGFjY3VyYWN5X292ZXJhbGx0cmFpbmluZ19wX3N1bW1hcnksCiAgZHYgPSBNZWFuLAogIHdpZCA9IFBhcnRpY2lwYW50LAogIHdpdGhpbiA9IGMoR3VpZGUsIEJsb2NrKQopCmBgYAoKIyMgRXhwZXJ0IFRyYWluaW5nCgpgYGB7cn0KYWNjdXJhY3lfcF9leHBlcnRfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKFBoYXNlID09ICJUcmFpbmluZyIgJiBNb2RlID09ICJFeHBlcnQiICYgIUlzT3V0bGllcikgJT4lCiAgZ3JvdXBfYnkoUGFydGljaXBhbnQsIEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShNZWFuID0gbWVhbihSZXN1bHQpLCAuZ3JvdXBzPSJkcm9wIikKYWNjdXJhY3lfcF9leHBlcnRfc3VtbWFyeQoKZXhwZXJ0YWNjX29jdG8gPC0gc3Vic2V0KGFjY3VyYWN5X3BfZXhwZXJ0X3N1bW1hcnksICBHdWlkZSA9PSAiT2N0byIsIE1lYW4sIGRyb3AgPSBUUlVFKQpleHBlcnRhY2Nfc2hlZXQgPC0gc3Vic2V0KGFjY3VyYWN5X3BfZXhwZXJ0X3N1bW1hcnksICBHdWlkZSA9PSAiU2hlZXQiLCBNZWFuLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShleHBlcnRhY2Nfc2hlZXQsIGV4cGVydGFjY19vY3RvKQoKZXhwZXJ0YWNjX2IxIDwtIHN1YnNldChhY2N1cmFjeV9wX2V4cGVydF9zdW1tYXJ5LCAgQmxvY2sgPT0gIkIxIiwgTWVhbiwgZHJvcCA9IFRSVUUpCmV4cGVydGFjY19iMiA8LSBzdWJzZXQoYWNjdXJhY3lfcF9leHBlcnRfc3VtbWFyeSwgIEJsb2NrID09ICJCMiIsIE1lYW4sIGRyb3AgPSBUUlVFKQpleHBlcnRhY2NfYjMgPC0gc3Vic2V0KGFjY3VyYWN5X3BfZXhwZXJ0X3N1bW1hcnksICBCbG9jayA9PSAiQjMiLCBNZWFuLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShleHBlcnRhY2NfYjMsIGV4cGVydGFjY19iMikKCmFjY3VyYWN5X2V4cGVydF9zdW1tYXJ5IDwtIGFjY3VyYWN5X3BfZXhwZXJ0X3N1bW1hcnkgJT4lCiAgZ3JvdXBfYnkoR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKHN1bW1hcnlfd2l0aF9jaShNZWFuKSwgLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShMb3dlclZhbHVlID0gaWZfZWxzZShMb3dlclZhbHVlIDwgMCwgMCwgTG93ZXJWYWx1ZSkpCmFjY3VyYWN5X2V4cGVydF9zdW1tYXJ5CmBgYAoKCiMjIyBHcmFwaAoKYGBge3J9CmdncGxvdChkYXRhPWFjY3VyYWN5X2V4cGVydF9zdW1tYXJ5LCBhZXMoeD1CbG9jaywgeT1NZWFuVmFsdWUsIGdyb3VwPUd1aWRlKSkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49TG93ZXJWYWx1ZSwgeW1heD1VcHBlclZhbHVlKSwgd2lkdGg9LjMsIHBvc2l0aW9uPXBkKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1HdWlkZSksIHBvc2l0aW9uPXBkKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1HdWlkZSwgc2hhcGU9R3VpZGUpLCBzaXplPTMsIHBvc2l0aW9uPXBkKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXNwcmludGYoIiUuMGYiLCAxMDAqTWVhblZhbHVlKSwgY29sb3I9R3VpZGUpLCBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgICBzaXplPTQsIG51ZGdlX3g9aWZlbHNlKGFjY3VyYWN5X2V4cGVydF9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjMsIDAuMyksCiAgICAgICAgICAgIG51ZGdlX3k9aWZlbHNlKGFjY3VyYWN5X2V4cGVydF9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIDAuMSwgLTAuMSkKICApKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCoxMDApLGJyZWFrcyA9IHNlcSgwLDEsMC4yNSkpKwogICMgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoKSwgYnJlYWtzID0gc2VxKDAsMSwwLjI1KSkrCiAgZXhwYW5kX2xpbWl0cyh5PWMoMCwxKSkgKwogIGxhYnMoeD0iQmxvY2siLCB5PSJBY2N1cmFjeSAoJSkiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJCMS1UcmFpbiIsICJCMi1UcmFpbiIsICJCMy1UcmFpbiIpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI2QzNTQwMCIsICIjOTVhNWE2IikpKwogIGZhY2V0X2dyaWQoc2NhbGVzID0gImZyZWUiLCBzcGFjZSA9ICJmcmVlIikrCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDAsIHIgPSA1LCBiID0gMCwgbCA9IDApKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSA1LCByID0gMCwgYiA9IDAsIGwgPSAwKSkpCmBgYAoKCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm9ybWFsLgoKYGBge3J9Cm0gPSBhb3YoTWVhbiB+IEJsb2NrKkd1aWRlICsgRXJyb3IoUGFydGljaXBhbnQpLCBkYXRhID0gYWNjdXJhY3lfcF9leHBlcnRfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgQU5PVkEKYGBge3J9CmV6QU5PVkEoCiAgYWNjdXJhY3lfcF9leHBlcnRfc3VtbWFyeSwKICBkdiA9IE1lYW4sCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KGFjY3VyYWN5X3BfZXhwZXJ0X3N1bW1hcnkkTWVhbiwgCiAgICAgICAgICAgICAgICBhY2N1cmFjeV9wX2V4cGVydF9zdW1tYXJ5JEJsb2NrLCAKICAgICAgICAgICAgICAgIHBhaXJlZD1UUlVFLCAKICAgICAgICAgICAgICAgIHAuYWRqPSJib25mIikKYGBgCgojIyBOb3ZpY2UgVHJhaW5pbmcKCmBgYHtyfQphY2N1cmFjeV9wX25vdmljZV9zdW1tYXJ5IDwtIHRyaWFscyAlPiUKICBmaWx0ZXIoUGhhc2UgPT0gIlRyYWluaW5nIiAmIE1vZGUgPT0gIk5vdmljZSIgJiAhSXNPdXRsaWVyKSAlPiUKICBncm91cF9ieShQYXJ0aWNpcGFudCwgR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKE1lYW4gPSBtZWFuKFJlc3VsdCksIC5ncm91cHM9ImRyb3AiKQoKIyBiZWNhdXNlIFAxMSBoYXMgemVybyBub3ZpY2UgdHJpYWwgaW4gQjMsIHdlIGF2ZXJhZ2VkIHZhbHVlcyBiZXR3ZWVuIHRoYXQgb2YgQjEgYW5kIEIyCm5ld1JvdyA9IGMoIlAxMSIsICJTaGVldCIsICJUcmFpbmluZyIsICJCMyIsIDAuNjc4NTcxNDUpCiMgbWVyZ2UgbmV3IHJvdyBpbnRvIHRhYmxlCmFjY3VyYWN5X3Bfbm92aWNlX3N1bW1hcnkgPSByYmluZChhY2N1cmFjeV9wX25vdmljZV9zdW1tYXJ5LCBuZXdSb3cpCiMgY29udmVydCBmcm9tIGNoYXJhY3RlciB0byBudW1iZXJzCmFjY3VyYWN5X3Bfbm92aWNlX3N1bW1hcnkkTWVhbiA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihhY2N1cmFjeV9wX25vdmljZV9zdW1tYXJ5JE1lYW4pKQoKYWNjdXJhY3lfcF9ub3ZpY2Vfc3VtbWFyeQoKbm92aWNlYWNjX29jdG8gPC0gc3Vic2V0KGFjY3VyYWN5X3Bfbm92aWNlX3N1bW1hcnksICBHdWlkZSA9PSAiT2N0byIsIE1lYW4sIGRyb3AgPSBUUlVFKQpub3ZpY2VhY2Nfc2hlZXQgPC0gc3Vic2V0KGFjY3VyYWN5X3Bfbm92aWNlX3N1bW1hcnksICBHdWlkZSA9PSAiU2hlZXQiLCBNZWFuLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShub3ZpY2VhY2Nfc2hlZXQsIG5vdmljZWFjY19vY3RvKQoKYWNjdXJhY3lfbm92aWNlX3N1bW1hcnkgPC0gYWNjdXJhY3lfcF9ub3ZpY2Vfc3VtbWFyeSAlPiUKICBncm91cF9ieShHdWlkZSwgUGhhc2UsIEJsb2NrKSAlPiUKICBzdW1tYXJpemUoc3VtbWFyeV93aXRoX2NpKE1lYW4pLCAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgbXV0YXRlKExvd2VyVmFsdWUgPSBpZl9lbHNlKExvd2VyVmFsdWUgPCAwLCAwLCBMb3dlclZhbHVlKSkKYWNjdXJhY3lfbm92aWNlX3N1bW1hcnkKYGBgCgoKIyMjIEdyYXBoCgpgYGB7cn0KcGQgPC0gcG9zaXRpb25fZG9kZ2UoMC40KQoKZ2dwbG90KGRhdGE9YWNjdXJhY3lfbm92aWNlX3N1bW1hcnksIGFlcyh4PUJsb2NrLCB5PU1lYW5WYWx1ZSwgZ3JvdXA9R3VpZGUpKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1Mb3dlclZhbHVlLCB5bWF4PVVwcGVyVmFsdWUpLCB3aWR0aD0uMywgcG9zaXRpb249cGQpICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yPUd1aWRlKSwgcG9zaXRpb249cGQpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPUd1aWRlLCBzaGFwZT1HdWlkZSksIHNpemU9MywgcG9zaXRpb249cGQpKwogIGdlb21fdGV4dChhZXMobGFiZWw9c3ByaW50ZigiJS4wZiIsIDEwMCpNZWFuVmFsdWUpLCBjb2xvcj1HdWlkZSksIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICAgIHNpemU9NCwgbnVkZ2VfeD1pZmVsc2UoYWNjdXJhY3lfbm92aWNlX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgLTAuMywgMC4zKSwKICAgICAgICAgICAgbnVkZ2VfeT1pZmVsc2UoYWNjdXJhY3lfbm92aWNlX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgMC4wNSwgLTAuMDUpCiAgKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgqMTAwKSxicmVha3MgPSBzZXEoMCwxLDAuMjUpKSsKICAjIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9wZXJjZW50KCksIGJyZWFrcyA9IHNlcSgwLDEsMC4yNSkpKwogIGV4cGFuZF9saW1pdHMoeT1jKDAsMSkpKwogIGxhYnMoeD0iQmxvY2siLCB5PSJBY2N1cmFjeSAoJSkiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJCMS1UcmFpbiIsICJCMi1UcmFpbiIsICJCMy1UcmFpbiIpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI2QzNTQwMCIsICIjOTVhNWE2IikpKwogIGZhY2V0X2dyaWQoc2NhbGVzID0gImZyZWUiLCBzcGFjZSA9ICJmcmVlIikrCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDAsIHIgPSA1LCBiID0gMCwgbCA9IDApKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSA1LCByID0gMCwgYiA9IDAsIGwgPSAwKSkpCmBgYAoKCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm9ybWFsLgoKYGBge3J9Cm0gPSBhb3YoTWVhbiB+IEJsb2NrKkd1aWRlICsgRXJyb3IoUGFydGljaXBhbnQpLCBkYXRhID0gYWNjdXJhY3lfcF9ub3ZpY2Vfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgQU5PVkEKYGBge3J9CmV6QU5PVkEoCiAgYWNjdXJhY3lfcF9ub3ZpY2Vfc3VtbWFyeSwKICBkdiA9IE1lYW4sCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyBHdWVzcyAoUHJlLVRlc3QpCgpgYGB7cn0KYWNjdXJhY3lfcHJldGVzdF9wX3N1bW1hcnkgPC0gdHJpYWxzICU+JQogIGZpbHRlcihQaGFzZSA9PSAiUHJlVGVzdCIgJiAhSXNPdXRsaWVyKSAlPiUKICBncm91cF9ieShQYXJ0aWNpcGFudCwgR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKE1lYW4gPSBtZWFuKFJlc3VsdCksIC5ncm91cHM9ImRyb3AiKQphY2N1cmFjeV9wcmV0ZXN0X3Bfc3VtbWFyeQoKYWNjdXJhY3lfcHJldGVzdF9zdW1tYXJ5IDwtIGFjY3VyYWN5X3ByZXRlc3RfcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShzdW1tYXJ5X3dpdGhfY2koTWVhbiksIC5ncm91cHM9ImRyb3AiKSAlPiUKICBtdXRhdGUoTG93ZXJWYWx1ZSA9IGlmX2Vsc2UoTG93ZXJWYWx1ZSA8IDAsIDAsIExvd2VyVmFsdWUpKQoKcHJldGVzdGFjY19vY3RvIDwtIHN1YnNldChhY2N1cmFjeV9wcmV0ZXN0X3Bfc3VtbWFyeSwgIEd1aWRlID09ICJPY3RvIiwgTWVhbiwgZHJvcCA9IFRSVUUpCnByZXRlc3RhY2Nfc2hlZXQgPC0gc3Vic2V0KGFjY3VyYWN5X3ByZXRlc3RfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIlNoZWV0IiwgTWVhbiwgZHJvcCA9IFRSVUUpCk1lYW5EaWZmQ0kocHJldGVzdGFjY19zaGVldCwgcHJldGVzdGFjY19vY3RvKQoKYWNjdXJhY3lfcHJldGVzdF9zdW1tYXJ5CmBgYAojIyMgR3JhcGgKCmBgYHtyfQpnZ3Bsb3QoZGF0YT1hY2N1cmFjeV9wcmV0ZXN0X3N1bW1hcnksIGFlcyh4PUd1aWRlLCB5PU1lYW5WYWx1ZSwgZmlsbCA9IEd1aWRlKSkgKwogIGdlb21fYmFyKHNpemU9MyxzdGF0PSJpZGVudGl0eSIpKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49TG93ZXJWYWx1ZSwgeW1heD1VcHBlclZhbHVlKSwgd2lkdGg9LjMsIHBvc2l0aW9uPXBkKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1zcHJpbnRmKCIlLjBmIiwgMTAwKk1lYW5WYWx1ZSksIGNvbG9yPUd1aWRlKSwKICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgICAgc2l6ZT00LCBudWRnZV95ID0gMC4xCiAgKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgqMTAwKSxicmVha3MgPSBzZXEoMCwxLDAuMjUpKSsKICAjIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9wZXJjZW50KCksIGJyZWFrcyA9IHNlcSgwLDEsMC4yNSkpKwogIGV4cGFuZF9saW1pdHMoeT1jKDAsMSkpKwogIGxhYnMoeD0iR3VpZGUiLCB5PSJBY2N1cmFjeSAoJSkiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2QzNTQwMCIsICIjOTVhNWE2IiksbGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI2QzNTQwMCIsICIjOTVhNWE2IiksbGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBzY2FsZV9zaGFwZV9kaXNjcmV0ZShsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIHNjYWxlX2xpbmV0eXBlKGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gJ2dyZXknKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDAsIHIgPSA1LCBiID0gMCwgbCA9IDApKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSA1LCByID0gMCwgYiA9IDAsIGwgPSAwKSkpCmBgYAoKCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm9ybWFsLgoKYGBge3J9Cm0gPSBhb3YoTWVhbiB+IEd1aWRlICsgRXJyb3IoUGFydGljaXBhbnQpLCBkYXRhID0gYWNjdXJhY3lfcHJldGVzdF9wX3N1bW1hcnkpCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobSRXaXRoaW4pKQpwbG90Tm9ybWFsSGlzdG9ncmFtKHJlc2lkdWFscyhtJFdpdGhpbikpCnFxbm9ybShyZXNpZHVhbHMobSRXaXRoaW4pKTsgcXFsaW5lKHJlc2lkdWFscyhtJFdpdGhpbikpCmBgYAoKIyMjIEFOT1ZBCgpgYGB7cn0KZXpBTk9WQSgKICBhY2N1cmFjeV9wcmV0ZXN0X3Bfc3VtbWFyeSwKICBkdiA9IE1lYW4sCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSkKKQpgYGAKCiMjIFJlY2FsbCAoVGVzdCkKCmBgYHtyfQphY2N1cmFjeV90ZXN0X3Bfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKFBoYXNlID09ICJUZXN0IiAmICFJc091dGxpZXIpICU+JQogIGdyb3VwX2J5KFBhcnRpY2lwYW50LCBHdWlkZSwgUGhhc2UsIEJsb2NrKSAlPiUKICBzdW1tYXJpemUoTWVhbiA9IG1lYW4oUmVzdWx0KSwgLmdyb3Vwcz0iZHJvcCIpCmFjY3VyYWN5X3Rlc3RfcF9zdW1tYXJ5CgptYWludGVzdF9vY3RvIDwtIHN1YnNldChhY2N1cmFjeV90ZXN0X3Bfc3VtbWFyeSwgIEd1aWRlID09ICJPY3RvIiwgTWVhbiwgZHJvcCA9IFRSVUUpCm1haW50ZXN0X3NoZWV0IDwtIHN1YnNldChhY2N1cmFjeV90ZXN0X3Bfc3VtbWFyeSwgIEd1aWRlID09ICJTaGVldCIsIE1lYW4sIGRyb3AgPSBUUlVFKQpNZWFuRGlmZkNJKG1haW50ZXN0X3NoZWV0LCBtYWludGVzdF9vY3RvKQoKYWNjdXJhY3lfdGVzdF9zdW1tYXJ5IDwtIGFjY3VyYWN5X3Rlc3RfcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShzdW1tYXJ5X3dpdGhfY2koTWVhbiksIC5ncm91cHM9ImRyb3AiKSAlPiUKICBtdXRhdGUoTG93ZXJWYWx1ZSA9IGlmX2Vsc2UoTG93ZXJWYWx1ZSA8IDAsIDAsIExvd2VyVmFsdWUpKQoKYWNjdGVzdF9iMSA8LSBzdWJzZXQoYWNjdXJhY3lfdGVzdF9wX3N1bW1hcnksICBCbG9jayA9PSAiQjEiLCBNZWFuLCBkcm9wID0gVFJVRSkKYWNjdGVzdF9iMiA8LSBzdWJzZXQoYWNjdXJhY3lfdGVzdF9wX3N1bW1hcnksICBCbG9jayA9PSAiQjIiLCBNZWFuLCBkcm9wID0gVFJVRSkKYWNjdGVzdF9iMyA8LSBzdWJzZXQoYWNjdXJhY3lfdGVzdF9wX3N1bW1hcnksICBCbG9jayA9PSAiQjMiLCBNZWFuLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShhY2N0ZXN0X2IyLCBhY2N0ZXN0X2IxKQpNZWFuRGlmZkNJKGFjY3Rlc3RfYjMsIGFjY3Rlc3RfYjIpCgphY2N1cmFjeV90ZXN0X3N1bW1hcnkKYGBgCgoKIyMjIEdyYXBoCgpgYGB7cn0KcGQgPC0gcG9zaXRpb25fZG9kZ2UoMC40KQoKZ2dwbG90KGRhdGE9YWNjdXJhY3lfdGVzdF9zdW1tYXJ5LCBhZXMoeD1CbG9jaywgeT1NZWFuVmFsdWUsIGdyb3VwPUd1aWRlKSkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49TG93ZXJWYWx1ZSwgeW1heD1VcHBlclZhbHVlKSwgd2lkdGg9LjMsIHBvc2l0aW9uPXBkKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1HdWlkZSksIHBvc2l0aW9uPXBkKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1HdWlkZSwgc2hhcGU9R3VpZGUpLCBzaXplPTMsIHBvc2l0aW9uPXBkKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXNwcmludGYoIiUuMGYiLCAxMDAqTWVhblZhbHVlKSwgY29sb3I9R3VpZGUpLAogICAgICAgICAgICBzaXplPTQsIG51ZGdlX3g9aWZlbHNlKGFjY3VyYWN5X3Rlc3Rfc3VtbWFyeSRHdWlkZT09Ik9jdG8iLCAtMC40LCAwLjQpLAogICAgICAgICAgICBudWRnZV95PWlmZWxzZShhY2N1cmFjeV90ZXN0X3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgMC4xLCAtMC4xKQogICkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4KjEwMCksYnJlYWtzID0gc2VxKDAsMSwwLjI1KSkrCiAgIyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gbGFiZWxfcGVyY2VudCgpLCBicmVha3MgPSBzZXEoMCwxLDAuMjUpKSsKICBleHBhbmRfbGltaXRzKHk9YygwLDEpKSsKICBsYWJzKHg9IkJsb2NrIiwgeT0iQWNjdXJhY3kgKCUpIikrCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiQjEtVGVzdCIsICJCMi1UZXN0IiwgIkIzLVRlc3QiKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiNkMzU0MDAiLCAiIzk1YTVhNiIpLGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgc2NhbGVfc2hhcGVfZGlzY3JldGUobGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBzY2FsZV9saW5ldHlwZShsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIGZhY2V0X2dyaWQoc2NhbGVzID0gImZyZWUiLCBzcGFjZSA9ICJmcmVlIikrCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjUsIDAuMSksIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICdncmV5JyksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAwLCByID0gNSwgYiA9IDAsIGwgPSAwKSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gNSwgciA9IDAsIGIgPSAwLCBsID0gMCkpKQpgYGAKCgoKIyMjIEFzc3VtcHRpb25zClNoYXBpcm8gdGVzdCBwID4gMC4wNS4gVGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzIGlzIG5vcm1hbC4KCmBgYHtyfQptID0gYW92KE1lYW4gfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IGFjY3VyYWN5X3Rlc3RfcF9zdW1tYXJ5KQpzaGFwaXJvLnRlc3QocmVzaWR1YWxzKG0kV2l0aGluKSkKcGxvdE5vcm1hbEhpc3RvZ3JhbShyZXNpZHVhbHMobSRXaXRoaW4pKQpxcW5vcm0ocmVzaWR1YWxzKG0kV2l0aGluKSk7IHFxbGluZShyZXNpZHVhbHMobSRXaXRoaW4pKQpgYGAKCiMjIyBBTk9WQQpgYGB7cn0KZXpBTk9WQSgKICBhY2N1cmFjeV90ZXN0X3Bfc3VtbWFyeSwKICBkdiA9IE1lYW4sCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KGFjY3VyYWN5X3Rlc3RfcF9zdW1tYXJ5JE1lYW4sIAogICAgICAgICAgICAgICAgYWNjdXJhY3lfdGVzdF9wX3N1bW1hcnkkQmxvY2ssIAogICAgICAgICAgICAgICAgcGFpcmVkPVRSVUUsIAogICAgICAgICAgICAgICAgcC5hZGo9ImJvbmYiKQpgYGAKCiMjIEluY2lkZW50YWwgTGVhcm5pbmcgKFBvc3QtdGVzdCkKCmBgYHtyfQojIGV4Y2x1ZGluZyB0YXJnZXRzCmFjY3VyYWN5X3Bvc3R0ZXN0X3Bfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKFBoYXNlID09ICJQb3N0VGVzdCIgJiAhSXNPdXRsaWVyKSAlPiUKICBmaWx0ZXIoVHJpYWxOYW1lICE9ICJBYnUgRGhhYmkiICYgVHJpYWxOYW1lICE9ICJBbXN0ZXJkYW0iICYgVHJpYWxOYW1lICE9ICJEdWJhaSIgJiBUcmlhbE5hbWUgIT0gIkxvcyBBbmdlbGVzIiAmIFRyaWFsTmFtZSAhPSAiTWFkcmlkIiAmIFRyaWFsTmFtZSAhPSAiUGFyaXMiICYgVHJpYWxOYW1lICE9ICJTaW5nYXBvcmUiICYgVHJpYWxOYW1lICE9ICJUb2t5byIgJiBUcmlhbE5hbWUgIT0gIkF1c3RpbiIgJiBUcmlhbE5hbWUgIT0gIkRvaGEiICYgVHJpYWxOYW1lICE9ICJGcmFua2Z1cnQiICYgVHJpYWxOYW1lICE9ICJIb3VzdG9uIiAmIFRyaWFsTmFtZSAhPSAiTWlsYW4iICYgVHJpYWxOYW1lICE9ICJQcmFndWUiICYgVHJpYWxOYW1lICE9ICJTZW91bCIgJiBUcmlhbE5hbWUgIT0gIlRvcm9udG8iKSAlPiUKICBncm91cF9ieShQYXJ0aWNpcGFudCwgR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKE1lYW4gPSBtZWFuKFJlc3VsdCksIC5ncm91cHM9ImRyb3AiKQphY2N1cmFjeV9wb3N0dGVzdF9wX3N1bW1hcnkKCmFjY3VyYWN5cG9zdHRlc3Rfb2N0byA8LSBzdWJzZXQoYWNjdXJhY3lfcG9zdHRlc3RfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIk9jdG8iLCBNZWFuLCBkcm9wID0gVFJVRSkKYWNjdXJhY3lwb3N0dGVzdF9zaGVldCA8LSBzdWJzZXQoYWNjdXJhY3lfcG9zdHRlc3RfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIlNoZWV0IiwgTWVhbiwgZHJvcCA9IFRSVUUpCk1lYW5EaWZmQ0koYWNjdXJhY3lwb3N0dGVzdF9vY3RvLCBhY2N1cmFjeXBvc3R0ZXN0X3NoZWV0KQoKYWNjdXJhY3lfcG9zdHRlc3Rfc3VtbWFyeSA8LSBhY2N1cmFjeV9wb3N0dGVzdF9wX3N1bW1hcnkgJT4lCiAgZ3JvdXBfYnkoR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKHN1bW1hcnlfd2l0aF9jaShNZWFuKSwgLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShMb3dlclZhbHVlID0gaWZfZWxzZShMb3dlclZhbHVlIDwgMCwgMCwgTG93ZXJWYWx1ZSkpCmFjY3VyYWN5X3Bvc3R0ZXN0X3N1bW1hcnkKYGBgCgojIyMgR3JhcGgKCmBgYHtyfQpnZ3Bsb3QoZGF0YT1hY2N1cmFjeV9wb3N0dGVzdF9zdW1tYXJ5LCBhZXMoeD1HdWlkZSwgeT1NZWFuVmFsdWUsIGZpbGwgPSBHdWlkZSkpICsKICBnZW9tX2JhcihzaXplPTMsc3RhdD0iaWRlbnRpdHkiKSsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPUxvd2VyVmFsdWUsIHltYXg9VXBwZXJWYWx1ZSksIHdpZHRoPS4zLCBwb3NpdGlvbj1wZCkgKwogIGdlb21fdGV4dChhZXMobGFiZWw9c3ByaW50ZigiJS4wZiIsIDEwMCpNZWFuVmFsdWUpLCBjb2xvcj1HdWlkZSksCiAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICAgIHNpemU9NCwgbnVkZ2VfeSA9IDAuMDUsIG51ZGdlX3ggPSAwLjMKICApKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmdW5jdGlvbih4KSBwYXN0ZTAoeCoxMDApLGJyZWFrcyA9IHNlcSgwLDEsMC4yNSkpKwogICMgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX3BlcmNlbnQoKSwgYnJlYWtzID0gc2VxKDAsMSwwLjI1KSkrCiAgZXhwYW5kX2xpbWl0cyh5PWMoMCwxKSkrCiAgbGFicyh4PSJHdWlkZSIsIHk9IkFjY3VyYWN5ICglKSIpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjZDM1NDAwIiwgIiM5NWE1YTYiKSxsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjZDM1NDAwIiwgIiM5NWE1YTYiKSxsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIHNjYWxlX3NoYXBlX2Rpc2NyZXRlKGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgc2NhbGVfbGluZXR5cGUobGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMCwgciA9IDUsIGIgPSAwLCBsID0gMCkpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDUsIHIgPSAwLCBiID0gMCwgbCA9IDApKSkKYGBgCgoKCiMjIyBBc3N1bXB0aW9ucwpTaGFwaXJvIHRlc3QgcCA+IDAuMDUuIFRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlc2lkdWFscyBpcyBub3JtYWwuCgpgYGB7cn0KbSA9IGFvdihNZWFuIH4gR3VpZGUgKyBFcnJvcihQYXJ0aWNpcGFudCksIGRhdGEgPSBhY2N1cmFjeV9wb3N0dGVzdF9wX3N1bW1hcnkpCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobSRXaXRoaW4pKQpwbG90Tm9ybWFsSGlzdG9ncmFtKHJlc2lkdWFscyhtJFdpdGhpbikpCnFxbm9ybShyZXNpZHVhbHMobSRXaXRoaW4pKTsgcXFsaW5lKHJlc2lkdWFscyhtJFdpdGhpbikpCmBgYAoKIyMjIEFOT1ZBCgpgYGB7cn0KZXpBTk9WQSgKICBhY2N1cmFjeV9wb3N0dGVzdF9wX3N1bW1hcnksCiAgZHYgPSBNZWFuLAogIHdpZCA9IFBhcnRpY2lwYW50LAogIHdpdGhpbiA9IGMoR3VpZGUpCikKYGBgCgojIyBMZWFybmluZyBDdXJ2ZSAoY29tYmluZWQsIG9ubHkgOCB0cmFpbmVkIGdlc3R1cmVzKQoKYGBge3J9CnRhcmdldHMgPC0gYygiQWJ1IERoYWJpIiwgIkFtc3RlcmRhbSIsICJEdWJhaSIsICJMb3MgQW5nZWxlcyIsICJNYWRyaWQiLCAiUGFyaXMiLCAiU2luZ2Fwb3JlIiwgIlRva3lvIiwgIkF1c3RpbiIsICJEb2hhIiwgIkZyYW5rZnVydCIsICJIb3VzdG9uIiwgIk1pbGFuIiwgIlByYWd1ZSIsICJTZW91bCIsICJUb3JvbnRvIikKCmN1cnZlX3Bfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKFRyaWFsTmFtZSAlaW4lIHRhcmdldHMgJiBQaGFzZSE9IlRyYWluaW5nIiAmICFJc091dGxpZXIpICU+JQogIG11dGF0ZShQaGFzZU5hbWUgPSBpZmVsc2UoUGhhc2U9PSJUZXN0IiAmIEJsb2NrPT0iQjEiLCAiVGVzdCBCMSIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFBoYXNlPT0iVGVzdCIgJiBCbG9jaz09IkIyIiwgIlRlc3QgQjIiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZShQaGFzZT09IlRlc3QiICYgQmxvY2s9PSJCMyIsICJUZXN0IEIzIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUGhhc2U9PSJQcmVUZXN0IiwgIlByZVRlc3QiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZShQaGFzZT09IlBvc3RUZXN0IiwgIlBvc3RUZXN0IixOQSkpKSkpKSAlPiUKICBtdXRhdGUoUGhhc2VOYW1lID0gZmN0X3JlbGV2ZWwoUGhhc2VOYW1lLCAKICAgICAgICAgICAgIlByZVRlc3QiLCAiVGVzdCBCMSIsICJUZXN0IEIyIiwgIlRlc3QgQjMiLCAiUG9zdFRlc3QiKSkgJT4lCiAgbXV0YXRlKFBoYXNlTmFtZSA9IGFzLmZhY3RvcihQaGFzZU5hbWUpKSAlPiUKICBncm91cF9ieShQYXJ0aWNpcGFudCwgR3VpZGUsIFBoYXNlTmFtZSkgJT4lCiAgc3VtbWFyaXplKE1lYW4gPSBtZWFuKFJlc3VsdCksIC5ncm91cHM9ImRyb3AiKQpjdXJ2ZV9wX3N1bW1hcnkKCmN1cnZlX3N1bW1hcnkgPC0gY3VydmVfcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLCBQaGFzZU5hbWUpICU+JQogIHN1bW1hcml6ZShzdW1tYXJ5X3dpdGhfY2koTWVhbiksIC5ncm91cHM9ImRyb3AiKSAlPiUKICBtdXRhdGUoTG93ZXJWYWx1ZSA9IGlmX2Vsc2UoTG93ZXJWYWx1ZSA8IDAsIDAsIExvd2VyVmFsdWUpKQpjdXJ2ZV9zdW1tYXJ5CgoKY3VydmVfdGVzdEIzIDwtIHN1YnNldChjdXJ2ZV9wX3N1bW1hcnksICBQaGFzZU5hbWUgPT0gIlRlc3QgQjMiLCBNZWFuLCBkcm9wID0gVFJVRSkKY3VydmVfcG9zdHRlc3QgPC0gc3Vic2V0KGN1cnZlX3Bfc3VtbWFyeSwgIFBoYXNlTmFtZSA9PSAiUG9zdFRlc3QiLCBNZWFuLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShjdXJ2ZV9wb3N0dGVzdCwgY3VydmVfdGVzdEIzKQpgYGAKCiMjIyBHcmFwaAoKYGBge3J9CnBkIDwtIHBvc2l0aW9uX2RvZGdlKDAuNCkKCmdncGxvdChkYXRhPWN1cnZlX3N1bW1hcnksIGFlcyh4PVBoYXNlTmFtZSwgeT1NZWFuVmFsdWUsIGdyb3VwPUd1aWRlKSkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49TG93ZXJWYWx1ZSwgeW1heD1VcHBlclZhbHVlKSwgd2lkdGg9LjMsIHBvc2l0aW9uPXBkKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1HdWlkZSksIHBvc2l0aW9uPXBkKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1HdWlkZSwgc2hhcGU9R3VpZGUpLCBzaXplPTMsIHBvc2l0aW9uPXBkKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXNwcmludGYoIiUuMGYiLCAxMDAqTWVhblZhbHVlKSwgY29sb3I9R3VpZGUpLAogICAgICAgICAgICBzaXplPTQsIG51ZGdlX3g9aWZlbHNlKGN1cnZlX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgLTAuMywgMC4zKSwKICAgICAgICAgICAgbnVkZ2VfeT1pZmVsc2UoY3VydmVfc3VtbWFyeSRHdWlkZT09Ik9jdG8iLCAwLjEsIC0wLjEpLAogICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgqMTAwKSxicmVha3MgPSBzZXEoMCwxLDAuMjUpKSsKICAjIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9wZXJjZW50KCksIGJyZWFrcyA9IHNlcSgwLDEsMC4yNSkpKwogIGV4cGFuZF9saW1pdHMoeT1jKDAsMSkpKwogIGxhYnMoeD0iUGhhc2UiLCB5PSJBY2N1cmFjeSAoJSkiKSsKICAjIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkIxLVRlc3QiLCAiQjItVGVzdCIsICJCMy1UZXN0IikpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjZDM1NDAwIiwgIiM5NWE1YTYiKSxsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIHNjYWxlX3NoYXBlX2Rpc2NyZXRlKGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgc2NhbGVfbGluZXR5cGUobGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBmYWNldF9ncmlkKHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIpKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC41LCAwLjEpLCBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMCwgciA9IDUsIGIgPSAwLCBsID0gMCkpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDUsIHIgPSAwLCBiID0gMCwgbCA9IDApKSkKYGBgCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm9ybWFsLgoKYGBge3J9Cm0gPSBhb3YoTWVhbiB+IFBoYXNlTmFtZSpHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IGN1cnZlX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgQU5PVkEKYGBge3J9CiMgY3VydmVfcF9zdW1tYXJ5X25ldyA9IGZpbHRlcihjdXJ2ZV9wX3N1bW1hcnksIFBoYXNlTmFtZT09IlRlc3QgQjMiIHwgUGhhc2VOYW1lPT0iUG9zdFRlc3QiKQojIGN1cnZlX3Bfc3VtbWFyeV9uZXcKCmV6QU5PVkEoCiAgY3VydmVfcF9zdW1tYXJ5LAogIGR2ID0gTWVhbiwKICB3aWQgPSBQYXJ0aWNpcGFudCwKICB3aXRoaW4gPSBjKEd1aWRlLCBQaGFzZU5hbWUpCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KGN1cnZlX3Bfc3VtbWFyeSRNZWFuLCAKICAgICAgICAgICAgICAgIGN1cnZlX3Bfc3VtbWFyeSRQaGFzZU5hbWUsIAogICAgICAgICAgICAgICAgcGFpcmVkPVRSVUUsIAogICAgICAgICAgICAgICAgcC5hZGo9ImJvbmYiKQpgYGAKCiMgT1RIRVJTCgojIyBFeHBlcnQgTW9kZSBSYXRlIChkdXJpbmcgVHJhaW5pbmcpCmBgYHtyfQpleHBlcnRwcm9wb3J0aW9uX3Bfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKFBoYXNlID09ICJUcmFpbmluZyIgJiAhSXNPdXRsaWVyKSAlPiUKICBncm91cF9ieShQYXJ0aWNpcGFudCwgR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKEV4cGVydENvdW50ID0gc3VtKE1vZGU9PSJFeHBlcnQiKSwgCiAgICAgICAgICAgIFRvdGFsID0gc3VtKE1vZGU9PSJOb3ZpY2UiKSArIHN1bShNb2RlPT0iRXhwZXJ0IiksCiAgICAgICAgICAgIEV4cGVydFBlcmNlbnQgPSAoc3VtKE1vZGU9PSJFeHBlcnQiKS9Ub3RhbCksCiAgICAgICAgICAgIC5ncm91cHM9ImRyb3AiKQpleHBlcnRwcm9wb3J0aW9uX3Bfc3VtbWFyeQoKZXhwZXJ0cHJvX29jdG8gPC0gc3Vic2V0KGV4cGVydHByb3BvcnRpb25fcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIk9jdG8iLCBFeHBlcnRQZXJjZW50LCBkcm9wID0gVFJVRSkKZXhwZXJ0cHJvX3NoZWV0IDwtIHN1YnNldChleHBlcnRwcm9wb3J0aW9uX3Bfc3VtbWFyeSwgIEd1aWRlID09ICJTaGVldCIsIEV4cGVydFBlcmNlbnQsIGRyb3AgPSBUUlVFKQpNZWFuRGlmZkNJKGV4cGVydHByb19zaGVldCwgZXhwZXJ0cHJvX29jdG8pCgpleHBlcnRwcm9fYjEgPC0gc3Vic2V0KGV4cGVydHByb3BvcnRpb25fcF9zdW1tYXJ5LCAgQmxvY2sgPT0gIkIxIiwgRXhwZXJ0UGVyY2VudCwgZHJvcCA9IFRSVUUpCmV4cGVydHByb19iMiA8LSBzdWJzZXQoZXhwZXJ0cHJvcG9ydGlvbl9wX3N1bW1hcnksICBCbG9jayA9PSAiQjIiLCBFeHBlcnRQZXJjZW50LCBkcm9wID0gVFJVRSkKZXhwZXJ0cHJvX2IzIDwtIHN1YnNldChleHBlcnRwcm9wb3J0aW9uX3Bfc3VtbWFyeSwgIEJsb2NrID09ICJCMyIsIEV4cGVydFBlcmNlbnQsIGRyb3AgPSBUUlVFKQpNZWFuRGlmZkNJKGV4cGVydHByb19iMiwgZXhwZXJ0cHJvX2IxKQpNZWFuRGlmZkNJKGV4cGVydHByb19iMywgZXhwZXJ0cHJvX2IxKQoKZXhwZXJ0cHJvcG9ydGlvbl9zdW1tYXJ5IDwtIGV4cGVydHByb3BvcnRpb25fcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShzdW1tYXJ5X3dpdGhfY2koRXhwZXJ0UGVyY2VudCksIC5ncm91cHM9ImRyb3AiKSAlPiUKICBtdXRhdGUoTG93ZXJWYWx1ZSA9IGlmX2Vsc2UoTG93ZXJWYWx1ZSA8IDAsIDAsIExvd2VyVmFsdWUpKQpleHBlcnRwcm9wb3J0aW9uX3N1bW1hcnkKYGBgCgojIyMgR3JhcGgKCmBgYHtyfQpwZCA8LSBwb3NpdGlvbl9kb2RnZSgwLjQpCgpnZ3Bsb3QoZGF0YT1leHBlcnRwcm9wb3J0aW9uX3N1bW1hcnksIGFlcyh4PUJsb2NrLCB5PU1lYW5WYWx1ZSwgZ3JvdXA9R3VpZGUpKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1Mb3dlclZhbHVlLCB5bWF4PVVwcGVyVmFsdWUpLCB3aWR0aD0uMywgcG9zaXRpb249cGQpICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yPUd1aWRlKSwgcG9zaXRpb249cGQpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPUd1aWRlLCBzaGFwZT1HdWlkZSksIHNpemU9MywgcG9zaXRpb249cGQpKwogIGdlb21fdGV4dChhZXMobGFiZWw9c3ByaW50ZigiJS4wZiIsIDEwMCpNZWFuVmFsdWUpLCBjb2xvcj1HdWlkZSksCiAgICAgICAgICAgIHNpemU9NCwgbnVkZ2VfeD1pZmVsc2UoZXhwZXJ0cHJvcG9ydGlvbl9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjM1LCAwLjM1KSwKICAgICAgICAgICAgbnVkZ2VfeT1pZmVsc2UoZXhwZXJ0cHJvcG9ydGlvbl9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjE1LCAwLjE1KQogICkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4KjEwMCksYnJlYWtzID0gc2VxKDAsMSwwLjI1KSkrCiAgIyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gbGFiZWxfcGVyY2VudCgpLCBicmVha3MgPSBzZXEoMCwxLDAuMjUpKSsKICBleHBhbmRfbGltaXRzKHk9YygwLDEpKSsKICBsYWJzKHg9IkJsb2NrIiwgeT0iVXNhZ2UgUmF0ZSAoJSkiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJCMS1UcmFpbiIsICJCMi1UcmFpbiIsICJCMy1UcmFpbiIpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI2QzNTQwMCIsICIjOTVhNWE2IiksbGFiZWxzPWMoIk9DVE9QT0NVUyIsIkNSSUJTSEVFVCIpKSsKICBzY2FsZV9zaGFwZV9kaXNjcmV0ZShsYWJlbHM9YygiT0NUT1BPQ1VTIiwiQ1JJQlNIRUVUIikpKwogIHNjYWxlX2xpbmV0eXBlKGxhYmVscz1jKCJPQ1RPUE9DVVMiLCJDUklCU0hFRVQiKSkrCiAgZmFjZXRfZ3JpZChzY2FsZXMgPSAiZnJlZSIsIHNwYWNlID0gImZyZWUiKSsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikrCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNSwgMC4xKSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gJ2dyZXknKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDAsIHIgPSA1LCBiID0gMCwgbCA9IDApKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSA1LCByID0gMCwgYiA9IDAsIGwgPSAwKSkpCmBgYAoKIyMjIEFzc3VtcHRpb25zClNoYXBpcm8gdGVzdCBwID4gMC4wNS4gVGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzIGlzIG5vcm1hbC4KCmBgYHtyfQptID0gYW92KEV4cGVydFBlcmNlbnQgfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IGV4cGVydHByb3BvcnRpb25fcF9zdW1tYXJ5KQpzaGFwaXJvLnRlc3QocmVzaWR1YWxzKG0kV2l0aGluKSkKcGxvdE5vcm1hbEhpc3RvZ3JhbShyZXNpZHVhbHMobSRXaXRoaW4pKQpxcW5vcm0ocmVzaWR1YWxzKG0kV2l0aGluKSk7IHFxbGluZShyZXNpZHVhbHMobSRXaXRoaW4pKQpgYGAKCiMjIyBBTk9WQQpgYGB7cn0KZXpBTk9WQSgKICBleHBlcnRwcm9wb3J0aW9uX3Bfc3VtbWFyeSwKICBkdiA9IEV4cGVydFBlcmNlbnQsCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KGV4cGVydHByb3BvcnRpb25fcF9zdW1tYXJ5JEV4cGVydFBlcmNlbnQsIAogICAgICAgICAgICAgICAgZXhwZXJ0cHJvcG9ydGlvbl9wX3N1bW1hcnkkQmxvY2ssIAogICAgICAgICAgICAgICAgcGFpcmVkPVRSVUUsIAogICAgICAgICAgICAgICAgcC5hZGo9ImJvbmYiKQpgYGAKCiMjIEV4cGxvcmF0aW9uIE1vZGUgUmF0ZSAoZHVyaW5nIFRyYWluaW5nKQoKYGBge3J9CmV4cGxvcmVwcm9wX3Bfc3VtbWFyeSA8LSB0cmlhbHMgJT4lCiAgZmlsdGVyKFBoYXNlID09ICJUcmFpbmluZyIgJiAhSXNPdXRsaWVyKSAlPiUKICBtdXRhdGUoaXNFeHBsb3JpbmcgPSBpZmVsc2UoR3JpcER1cmF0aW9uPjAsIDEsIDApKSAlPiUKICBncm91cF9ieShQYXJ0aWNpcGFudCwgR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKEZyZXF1ZW5jeSA9IHN1bShpc0V4cGxvcmluZyksCiAgICAgICAgICAgIFRvdGFsID0gc3VtKE1vZGU9PSJOb3ZpY2UiKSArIHN1bShNb2RlPT0iRXhwZXJ0IiksCiAgICAgICAgICAgIFByb3BvcnRpb24gPSAoRnJlcXVlbmN5L1RvdGFsKSwKICAgICAgICAgICAgLmdyb3Vwcz0iZHJvcCIpCmV4cGxvcmVwcm9wX3Bfc3VtbWFyeQoKZXhwbG9yZXByb3Bfc3VtbWFyeSA8LSBleHBsb3JlcHJvcF9wX3N1bW1hcnkgJT4lCiAgZ3JvdXBfYnkoR3VpZGUsIFBoYXNlLCBCbG9jaykgJT4lCiAgc3VtbWFyaXplKHN1bW1hcnlfd2l0aF9jaShQcm9wb3J0aW9uKSwgLmdyb3Vwcz0iZHJvcCIpICU+JQogIG11dGF0ZShMb3dlclZhbHVlID0gaWZfZWxzZShMb3dlclZhbHVlIDwgMCwgMCwgTG93ZXJWYWx1ZSkpCmV4cGxvcmVwcm9wX3N1bW1hcnkKCmV4cGxvcmVwcm9fb2N0byA8LSBzdWJzZXQoZXhwbG9yZXByb3BfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIk9jdG8iLCBQcm9wb3J0aW9uLCBkcm9wID0gVFJVRSkKZXhwbG9yZXByb19zaGVldCA8LSBzdWJzZXQoZXhwbG9yZXByb3BfcF9zdW1tYXJ5LCAgR3VpZGUgPT0gIlNoZWV0IiwgUHJvcG9ydGlvbiwgZHJvcCA9IFRSVUUpCk1lYW5EaWZmQ0koZXhwbG9yZXByb19zaGVldCwgZXhwbG9yZXByb19vY3RvKQoKZXhwbG9yZXByb19iMSA8LSBzdWJzZXQoZXhwbG9yZXByb3BfcF9zdW1tYXJ5LCAgQmxvY2sgPT0gIkIxIiwgUHJvcG9ydGlvbiwgZHJvcCA9IFRSVUUpCmV4cGxvcmVwcm9fYjIgPC0gc3Vic2V0KGV4cGxvcmVwcm9wX3Bfc3VtbWFyeSwgIEJsb2NrID09ICJCMiIsIFByb3BvcnRpb24sIGRyb3AgPSBUUlVFKQpleHBsb3JlcHJvX2IzIDwtIHN1YnNldChleHBsb3JlcHJvcF9wX3N1bW1hcnksICBCbG9jayA9PSAiQjMiLCBQcm9wb3J0aW9uLCBkcm9wID0gVFJVRSkKTWVhbkRpZmZDSShleHBsb3JlcHJvX2IyLCBleHBsb3JlcHJvX2IxKQpNZWFuRGlmZkNJKGV4cGxvcmVwcm9fYjMsIGV4cGxvcmVwcm9fYjIpCmBgYAoKIyMjIEdyYXBoCgpgYGB7cn0KcGQgPC0gcG9zaXRpb25fZG9kZ2UoMC40KQoKZ2dwbG90KGRhdGE9ZXhwbG9yZXByb3Bfc3VtbWFyeSwgYWVzKHg9QmxvY2ssIHk9TWVhblZhbHVlLCBncm91cD1HdWlkZSkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPUxvd2VyVmFsdWUsIHltYXg9VXBwZXJWYWx1ZSksIHdpZHRoPS4zLCBwb3NpdGlvbj1wZCkgKwogIGdlb21fbGluZShhZXMoY29sb3I9R3VpZGUpLCBwb3NpdGlvbj1wZCkrCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9R3VpZGUsIHNoYXBlPUd1aWRlKSwgc2l6ZT0zLCBwb3NpdGlvbj1wZCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1zcHJpbnRmKCIlLjBmIiwgMTAwKk1lYW5WYWx1ZSksIGNvbG9yPUd1aWRlKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgICAgc2l6ZT00LCBudWRnZV94PWlmZWxzZShleHBsb3JlcHJvcF9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjMsIDAuMyksCiAgICAgICAgICAgIG51ZGdlX3k9aWZlbHNlKGV4cGxvcmVwcm9wX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgLTAuMDUsIDAuMDUpCiAgKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgcGFzdGUwKHgqMTAwKSxicmVha3MgPSBzZXEoMCwxLDAuMjUpKSsKICAjIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9wZXJjZW50KCksIGJyZWFrcyA9IHNlcSgwLDEsMC4yNSkpKwogIGV4cGFuZF9saW1pdHMoeT1jKDAsMSkpKwogIGxhYnMoeD0iQmxvY2siLCB5PSJVc2FnZSBSYXRlICglKSIpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIkIxLVRyYWluIiwgIkIyLVRyYWluIiwgIkIzLVRyYWluIikpKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjZDM1NDAwIiwgIiM5NWE1YTYiKSkrCiAgZmFjZXRfZ3JpZChzY2FsZXMgPSAiZnJlZSIsIHNwYWNlID0gImZyZWUiKSsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxMikrCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICdncmV5JyksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMCwgciA9IDUsIGIgPSAwLCBsID0gMCkpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDUsIHIgPSAwLCBiID0gMCwgbCA9IDApKSkKYGBgCgojIyMgQXNzdW1wdGlvbnMKU2hhcGlybyB0ZXN0IHAgPCAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm90IG5vcm1hbC4KCmBgYHtyfQptID0gYW92KFByb3BvcnRpb24gfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IGV4cGxvcmVwcm9wX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgRGF0YSBUcmFuc2Zvcm1hdGlvbgpTaGFwaXJvIHRlc3QgcCA+IDAuMDUuIFRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlc2lkdWFscyBpcyBub3cgbm9ybWFsLgoKYGBge3J9CmV4cGxvcmVwcm9wX3Bfc3VtbWFyeSRUcmFuc1ZhbCA9IHNxcnQoZXhwbG9yZXByb3BfcF9zdW1tYXJ5JFByb3BvcnRpb24pCm0gPSBhb3YoVHJhbnNWYWwgfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IGV4cGxvcmVwcm9wX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgQU5PVkEKYGBge3J9CmV6QU5PVkEoCiAgZXhwbG9yZXByb3BfcF9zdW1tYXJ5LAogIGR2ID0gVHJhbnNWYWwsCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KGV4cGxvcmVwcm9wX3Bfc3VtbWFyeSRUcmFuc1ZhbCwgCiAgICAgICAgICAgICAgICBleHBsb3JlcHJvcF9wX3N1bW1hcnkkQmxvY2ssIAogICAgICAgICAgICAgICAgcGFpcmVkPVRSVUUsIAogICAgICAgICAgICAgICAgcC5hZGo9ImJvbmYiKQpgYGAKCiMjIE9DVE8gRXhwbG9yYXRpb24gTW9kZSBSYXRlIChkdXJpbmcgVHJhaW5pbmcpCgpgYGB7cn0KZXhwbG9yZXByb3Bfb2N0b19wX3N1bW1hcnkgPC0gdHJpYWxzICU+JQogIGZpbHRlcihHdWlkZSA9PSAiT2N0byIgJiBQaGFzZSA9PSAiVHJhaW5pbmciICYgIUlzT3V0bGllcikgJT4lCiAgbXV0YXRlKGlzRXhwbG9yaW5nID0gaWZlbHNlKEdyaXBEdXJhdGlvbj4wLCAxLCAwKSkgJT4lCiAgZ3JvdXBfYnkoUGFydGljaXBhbnQsIEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShGcmVxdWVuY3kgPSBzdW0oaXNFeHBsb3JpbmcpLAogICAgICAgICAgICBUb3RhbCA9IHN1bShNb2RlPT0iTm92aWNlIikgKyBzdW0oTW9kZT09IkV4cGVydCIpLAogICAgICAgICAgICBQcm9wb3J0aW9uID0gKEZyZXF1ZW5jeS9Ub3RhbCksCiAgICAgICAgICAgIC5ncm91cHM9ImRyb3AiKQpleHBsb3JlcHJvcF9vY3RvX3Bfc3VtbWFyeQoKZXhwbG9yZXByb3Bfb2N0b19zdW1tYXJ5IDwtIGV4cGxvcmVwcm9wX29jdG9fcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLEJsb2NrKSAlPiUKICBzdW1tYXJpemUoc3VtbWFyeV93aXRoX2NpKFByb3BvcnRpb24pLCAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgbXV0YXRlKExvd2VyVmFsdWUgPSBpZl9lbHNlKExvd2VyVmFsdWUgPCAwLCAwLCBMb3dlclZhbHVlKSkKZXhwbG9yZXByb3Bfb2N0b19zdW1tYXJ5CgpleHBsb3JlcHJvX29jdG9fYjEgPC0gc3Vic2V0KGV4cGxvcmVwcm9wX29jdG9fcF9zdW1tYXJ5LCAgQmxvY2sgPT0gIkIxIiwgUHJvcG9ydGlvbiwgZHJvcCA9IFRSVUUpCmV4cGxvcmVwcm9fb2N0b19iMiA8LSBzdWJzZXQoZXhwbG9yZXByb3Bfb2N0b19wX3N1bW1hcnksICBCbG9jayA9PSAiQjIiLCBQcm9wb3J0aW9uLCBkcm9wID0gVFJVRSkKZXhwbG9yZXByb19vY3RvX2IzIDwtIHN1YnNldChleHBsb3JlcHJvcF9vY3RvX3Bfc3VtbWFyeSwgIEJsb2NrID09ICJCMyIsIFByb3BvcnRpb24sIGRyb3AgPSBUUlVFKQpNZWFuRGlmZkNJKGV4cGxvcmVwcm9fb2N0b19iMiwgZXhwbG9yZXByb19vY3RvX2IxKQpNZWFuRGlmZkNJKGV4cGxvcmVwcm9fb2N0b19iMywgZXhwbG9yZXByb19vY3RvX2IxKQpgYGAKCiMjIyBHcmFwaAoKYGBge3J9CnBkIDwtIHBvc2l0aW9uX2RvZGdlKDAuNCkKCmdncGxvdChkYXRhPWV4cGxvcmVwcm9wX29jdG9fc3VtbWFyeSwgYWVzKHg9QmxvY2ssIHk9TWVhblZhbHVlLCBncm91cD1HdWlkZSkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPUxvd2VyVmFsdWUsIHltYXg9VXBwZXJWYWx1ZSksIHdpZHRoPS4zLCBwb3NpdGlvbj1wZCkgKwogIGdlb21fbGluZShhZXMoY29sb3I9R3VpZGUpLCBwb3NpdGlvbj1wZCkrCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9R3VpZGUsIHNoYXBlPUd1aWRlKSwgc2l6ZT0zLCBwb3NpdGlvbj1wZCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1zcHJpbnRmKCIlLjBmIiwgMTAwKk1lYW5WYWx1ZSksIGNvbG9yPUd1aWRlKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgICAgc2l6ZT00LCBudWRnZV94PWlmZWxzZShleHBsb3JlcHJvcF9vY3RvX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgLTAuMywgMC4zKSwKICAgICAgICAgICAgbnVkZ2VfeT1pZmVsc2UoZXhwbG9yZXByb3Bfb2N0b19zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjA1LCAwLjA1KQogICkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHBhc3RlMCh4KjEwMCksYnJlYWtzID0gc2VxKDAsMSwwLjI1KSkrCiAgIyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gbGFiZWxfcGVyY2VudCgpLCBicmVha3MgPSBzZXEoMCwxLDAuMjUpKSsKICBleHBhbmRfbGltaXRzKHk9YygwLDEpKSsKICBsYWJzKHg9IkJsb2NrIiwgeT0iVXNhZ2UgUmF0ZSAoJSkiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1jKCJCMS1UcmFpbiIsICJCMi1UcmFpbiIsICJCMy1UcmFpbiIpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI2QzNTQwMCIsICIjOTVhNWE2IikpKwogIGZhY2V0X2dyaWQoc2NhbGVzID0gImZyZWUiLCBzcGFjZSA9ICJmcmVlIikrCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTIpKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAnZ3JleScpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDAsIHIgPSA1LCBiID0gMCwgbCA9IDApKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSA1LCByID0gMCwgYiA9IDAsIGwgPSAwKSkpCmBgYAoKIyMjIEFzc3VtcHRpb25zClNoYXBpcm8gdGVzdCBwIDwgMC4wNS4gVGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzIGlzIG5vdCBub3JtYWwuCgpgYGB7cn0KbSA9IGFvdihQcm9wb3J0aW9uIH4gQmxvY2sgKyBFcnJvcihQYXJ0aWNpcGFudCksIGRhdGEgPSBleHBsb3JlcHJvcF9vY3RvX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgRGF0YSBUcmFuc2Zvcm1hdGlvbgpTaGFwaXJvIHRlc3QgcCA+IDAuMDUuIFRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlc2lkdWFscyBpcyBub3cgbm9ybWFsLgoKYGBge3J9CmV4cGxvcmVwcm9wX29jdG9fcF9zdW1tYXJ5JFRyYW5zVmFsID0gc3FydChleHBsb3JlcHJvcF9vY3RvX3Bfc3VtbWFyeSRQcm9wb3J0aW9uKQptID0gYW92KFRyYW5zVmFsIH4gQmxvY2sgKyBFcnJvcihQYXJ0aWNpcGFudCksIGRhdGEgPSBleHBsb3JlcHJvcF9vY3RvX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgQU5PVkEKYGBge3J9CmV6QU5PVkEoCiAgZXhwbG9yZXByb3Bfb2N0b19wX3N1bW1hcnksCiAgZHYgPSBUcmFuc1ZhbCwKICB3aWQgPSBQYXJ0aWNpcGFudCwKICB3aXRoaW4gPSBjKEJsb2NrKQopCmBgYAoKIyMjIFBhaXJ3aXNlIENvbXBhcmlzb24KYGBge3J9CnBhaXJ3aXNlLnQudGVzdChleHBsb3JlcHJvcF9vY3RvX3Bfc3VtbWFyeSRUcmFuc1ZhbCwgCiAgICAgICAgICAgICAgICBleHBsb3JlcHJvcF9vY3RvX3Bfc3VtbWFyeSRCbG9jaywgCiAgICAgICAgICAgICAgICBwYWlyZWQ9VFJVRSwgCiAgICAgICAgICAgICAgICBwLmFkaj0iYm9uZiIpCmBgYAoKIyMgRXhwbG9yZSBEdXJhdGlvbgoKYGBge3J9Cm1vZGVkdGltZV9wX3N1bW1hcnkgPC0gdHJpYWxzICU+JQogIGZpbHRlcihNb2RlID09ICJOb3ZpY2UiLCBQaGFzZSA9PSAiVHJhaW5pbmciICYgUmVzdWx0ID09IFRSVUUgJiBJc091dGxpZXIgPT0gRkFMU0UpICU+JQogIGdyb3VwX2J5KFBhcnRpY2lwYW50LCBHdWlkZSwgUGhhc2UsIEJsb2NrKSAlPiUKICBzdW1tYXJpemUoTWVhbklkbGUgPSBtZWFuKElkbGVEdXJhdGlvbiksIE1lYW5HcmlwID0gbWVhbihHcmlwRHVyYXRpb24pLCBNZWFuVHJpZ2dlciA9IG1lYW4oVHJpZ2dlckR1cmF0aW9uKSwgLmdyb3Vwcz0iZHJvcCIpCgojIGJlY2F1c2UgUDQgaGFzIHplcm8gbm92aWNlIHRyaWFsIGluIEIzLCB3ZSBhdmVyYWdlZCB2YWx1ZXMgYmV0d2VlbiB0aGF0IG9mIEIxIGFuZCBCMgpuZXdSb3cgPSBjKCJQNCIsICJTaGVldCIsICJUcmFpbmluZyIsICJCMyIsIDIuNTEwOTQ2NSwgNy43MjI4MjE0NSwgMS45NjgyNjgpCm1vZGVkdGltZV9wX3N1bW1hcnkgPSByYmluZChtb2RlZHRpbWVfcF9zdW1tYXJ5LCBuZXdSb3cpCiMgYmVjYXVzZSBQMTEgaGFzIHplcm8gbm92aWNlIHRyaWFsIGluIEIzLCB3ZSBhdmVyYWdlZCB2YWx1ZXMgYmV0d2VlbiB0aGF0IG9mIEIxIGFuZCBCMgpuZXdSb3cgPSBjKCJQMTEiLCAiU2hlZXQiLCAiVHJhaW5pbmciLCAiQjMiLCAzLjM5MTMzMzUsIDQuMDYzNSwgMS43MzQ3NSkKIyBtZXJnZSBuZXcgcm93IGludG8gdGFibGUKbW9kZWR0aW1lX3Bfc3VtbWFyeSA9IHJiaW5kKG1vZGVkdGltZV9wX3N1bW1hcnksIG5ld1JvdykKIyAjIGNvbnZlcnQgZnJvbSBjaGFyYWN0ZXIgdG8gbnVtYmVycwptb2RlZHRpbWVfcF9zdW1tYXJ5JE1lYW5JZGxlIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKG1vZGVkdGltZV9wX3N1bW1hcnkkTWVhbklkbGUpKQptb2RlZHRpbWVfcF9zdW1tYXJ5JE1lYW5HcmlwIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKG1vZGVkdGltZV9wX3N1bW1hcnkkTWVhbkdyaXApKQptb2RlZHRpbWVfcF9zdW1tYXJ5JE1lYW5UcmlnZ2VyIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKG1vZGVkdGltZV9wX3N1bW1hcnkkTWVhblRyaWdnZXIpKQoKbW9kZWR0aW1lX3Bfc3VtbWFyeQoKaWRsZXRpbWVfc3VtbWFyeSA8LSBtb2RlZHRpbWVfcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShzdW1tYXJ5X3dpdGhfY2koTWVhbklkbGUpLCAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgbXV0YXRlKExvd2VyVmFsdWUgPSBpZl9lbHNlKExvd2VyVmFsdWUgPCAwLCAwLCBMb3dlclZhbHVlKSkKaWRsZXRpbWVfc3VtbWFyeQoKZ3JpcHRpbWVfc3VtbWFyeSA8LSBtb2RlZHRpbWVfcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShzdW1tYXJ5X3dpdGhfY2koTWVhbkdyaXApLCAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgbXV0YXRlKExvd2VyVmFsdWUgPSBpZl9lbHNlKExvd2VyVmFsdWUgPCAwLCAwLCBMb3dlclZhbHVlKSkKZ3JpcHRpbWVfc3VtbWFyeQoKdHJpZ2dlcnRpbWVfc3VtbWFyeSA8LSBtb2RlZHRpbWVfcF9zdW1tYXJ5ICU+JQogIGdyb3VwX2J5KEd1aWRlLCBQaGFzZSwgQmxvY2spICU+JQogIHN1bW1hcml6ZShzdW1tYXJ5X3dpdGhfY2koTWVhblRyaWdnZXIpLCAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgbXV0YXRlKExvd2VyVmFsdWUgPSBpZl9lbHNlKExvd2VyVmFsdWUgPCAwLCAwLCBMb3dlclZhbHVlKSkKdHJpZ2dlcnRpbWVfc3VtbWFyeQpgYGAKCiMjIyBHcmFwaAoKYGBge3J9CnBkIDwtIHBvc2l0aW9uX2RvZGdlKDAuNCkKCmdncGxvdChkYXRhPWdyaXB0aW1lX3N1bW1hcnksIGFlcyh4PUJsb2NrLCB5PU1lYW5WYWx1ZSwgZ3JvdXA9R3VpZGUpKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1Mb3dlclZhbHVlLCB5bWF4PVVwcGVyVmFsdWUpLCB3aWR0aD0uMywgcG9zaXRpb249cGQpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlPUd1aWRlLCBjb2xvcj1HdWlkZSksIHBvc2l0aW9uPXBkKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1HdWlkZSwgc2hhcGU9R3VpZGUpLCBzaXplPTMsIHBvc2l0aW9uPXBkKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPWZvcm1hdChyb3VuZChNZWFuVmFsdWUsMyksbnNtYWxsPTMpLCBjb2xvcj1HdWlkZSksCiAgICAgICAgICAgIHNpemU9NCwgbnVkZ2VfeD1pZmVsc2UoZ3JpcHRpbWVfc3VtbWFyeSRHdWlkZT09Ik9jdG8iLCAtMC4zNSwgMC4zNSksCiAgICAgICAgICAgIG51ZGdlX3k9aWZlbHNlKGdyaXB0aW1lX3N1bW1hcnkkR3VpZGU9PSJPY3RvIiwgLTAuNCwgMC40KQogICkrCiAgZXhwYW5kX2xpbWl0cyh5PWMoMCw2KSkrCiAgbGFicyh4PSJCbG9jayIsIHk9IkV4cGxvcmUgRHVyYXRpb24gKHMpIikrCiAgZmFjZXRfZ3JpZCh+UGhhc2UsIHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAjbGVnZW5kLnBvc2l0aW9uID0gYygwLjg1LCAwLjg1KSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAwLCByID0gNSwgYiA9IDAsIGwgPSAwKSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gNSwgciA9IDAsIGIgPSAwLCBsID0gMCkpKQpgYGAKCiMjIyBBc3N1bXB0aW9ucwpTaGFwaXJvIHRlc3QgcCA8IDAuMDUuIFRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlc2lkdWFscyBpcyBub3Qgbm9ybWFsLgoKYGBge3J9Cm0gPSBhb3YoTWVhbkdyaXAgfiBCbG9jaypHdWlkZSArIEVycm9yKFBhcnRpY2lwYW50KSwgZGF0YSA9IG1vZGVkdGltZV9wX3N1bW1hcnkpCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobSRXaXRoaW4pKQpwbG90Tm9ybWFsSGlzdG9ncmFtKHJlc2lkdWFscyhtJFdpdGhpbikpCnFxbm9ybShyZXNpZHVhbHMobSRXaXRoaW4pKTsgcXFsaW5lKHJlc2lkdWFscyhtJFdpdGhpbikpCmBgYAoKIyMjIERhdGEgVHJhbnNmb3JtYXRpb24KU2hhcGlybyB0ZXN0IHAgPiAwLjA1LiBUaGUgZGlzdHJpYnV0aW9uIG9mIHRoZSByZXNpZHVhbHMgaXMgbm93IG5vcm1hbC4KCmBgYHtyfQptb2RlZHRpbWVfcF9zdW1tYXJ5JFRyYW5zVmFsID0gc3FydChtb2RlZHRpbWVfcF9zdW1tYXJ5JE1lYW5HcmlwKQptID0gYW92KFRyYW5zVmFsIH4gQmxvY2sqR3VpZGUgKyBFcnJvcihQYXJ0aWNpcGFudCksIGRhdGEgPSBtb2RlZHRpbWVfcF9zdW1tYXJ5KQpzaGFwaXJvLnRlc3QocmVzaWR1YWxzKG0kV2l0aGluKSkKcGxvdE5vcm1hbEhpc3RvZ3JhbShyZXNpZHVhbHMobSRXaXRoaW4pKQpxcW5vcm0ocmVzaWR1YWxzKG0kV2l0aGluKSk7IHFxbGluZShyZXNpZHVhbHMobSRXaXRoaW4pKQpgYGAKIyMjIEFOT1ZBCgpgYGB7cn0KZXpBTk9WQSgKICBtb2RlZHRpbWVfcF9zdW1tYXJ5LAogIGR2ID0gc3FydChNZWFuR3JpcCksCiAgd2lkID0gUGFydGljaXBhbnQsCiAgd2l0aGluID0gYyhHdWlkZSwgQmxvY2spCikKYGBgCgojIyMgUGFpcndpc2UgQ29tcGFyaXNvbgpgYGB7cn0KcGFpcndpc2UudC50ZXN0KHNxcnQobW9kZWR0aW1lX3Bfc3VtbWFyeSRNZWFuR3JpcCksIAogICAgICAgICAgICAgICAgbW9kZWR0aW1lX3Bfc3VtbWFyeSRCbG9jaywgCiAgICAgICAgICAgICAgICBwYWlyZWQ9VFJVRSwgCiAgICAgICAgICAgICAgICBwLmFkaj0iYm9uZiIpCmBgYAoKIyMgRHJhdyBEdXJhdGlvbgoKIyMjIEdyYXBoCgpgYGB7cn0KcGQgPC0gcG9zaXRpb25fZG9kZ2UoMC40KQoKZ2dwbG90KGRhdGE9dHJpZ2dlcnRpbWVfc3VtbWFyeSwgYWVzKHg9QmxvY2ssIHk9TWVhblZhbHVlLCBncm91cD1HdWlkZSkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPUxvd2VyVmFsdWUsIHltYXg9VXBwZXJWYWx1ZSksIHdpZHRoPS4zLCBwb3NpdGlvbj1wZCkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9R3VpZGUsIGNvbG9yPUd1aWRlKSwgcG9zaXRpb249cGQpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPUd1aWRlLCBzaGFwZT1HdWlkZSksIHNpemU9MywgcG9zaXRpb249cGQpKwogIGdlb21fdGV4dChhZXMobGFiZWw9Zm9ybWF0KHJvdW5kKE1lYW5WYWx1ZSwzKSxuc21hbGw9MyksIGNvbG9yPUd1aWRlKSwKICAgICAgICAgICAgc2l6ZT00LCBudWRnZV94PWlmZWxzZSh0cmlnZ2VydGltZV9zdW1tYXJ5JEd1aWRlPT0iT2N0byIsIC0wLjM1LCAwLjM1KSwKICAgICAgICAgICAgbnVkZ2VfeT1pZmVsc2UodHJpZ2dlcnRpbWVfc3VtbWFyeSRHdWlkZT09Ik9jdG8iLCAtMC40LCAwLjQpCiAgKSsKICBleHBhbmRfbGltaXRzKHk9YygwLDYpKSsKICBsYWJzKHg9IkJsb2NrIiwgeT0iRHJhdyBEdXJhdGlvbiAocykiKSsKICBmYWNldF9ncmlkKH5QaGFzZSwgc2NhbGVzID0gImZyZWUiLCBzcGFjZSA9ICJmcmVlIikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLjg1LCAwLjE1KSwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAwLCByID0gNSwgYiA9IDAsIGwgPSAwKSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gNSwgciA9IDAsIGIgPSAwLCBsID0gMCkpKQpgYGAKCiMjIyBBc3N1bXB0aW9ucwpTaGFwaXJvIHRlc3QgcCA+IDAuMDUuIFRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHJlc2lkdWFscyBpcyBub3JtYWwuCgpgYGB7cn0KbSA9IGFvdihNZWFuVHJpZ2dlciB+IEJsb2NrKkd1aWRlICsgRXJyb3IoUGFydGljaXBhbnQpLCBkYXRhID0gbW9kZWR0aW1lX3Bfc3VtbWFyeSkKc2hhcGlyby50ZXN0KHJlc2lkdWFscyhtJFdpdGhpbikpCnBsb3ROb3JtYWxIaXN0b2dyYW0ocmVzaWR1YWxzKG0kV2l0aGluKSkKcXFub3JtKHJlc2lkdWFscyhtJFdpdGhpbikpOyBxcWxpbmUocmVzaWR1YWxzKG0kV2l0aGluKSkKYGBgCgojIyMgQU5PVkEKCmBgYHtyfQplekFOT1ZBKAogIG1vZGVkdGltZV9wX3N1bW1hcnksCiAgZHYgPSBNZWFuVHJpZ2dlciwKICB3aWQgPSBQYXJ0aWNpcGFudCwKICB3aXRoaW4gPSBjKEd1aWRlLCBCbG9jaykKKQpgYGAKCiMgU1VCSkVDVElWRSBSQVRJTkcKCmBgYHtyfQpyYXRpbmdQYXJ0aWNpcGFudCA8LSByZWFkX2NzdigiLi9kYXRhMi5jc3YiKQpyYXRpbmdDb3VudCA8LSByZWFkX2NzdigiLi9kYXRhMy5jc3YiKQpvdmVyYWxsIDwtIHJlYWRfY3N2KCIuL2RhdGE0LmNzdiIpCmxlbmd0aCh1bmlxdWUob3ZlcmFsbCRQYXJ0aWNpcGFudCkpCnJhdGluZ1BhcnRpY2lwYW50CgpuYW1lcyhyYXRpbmdDb3VudClbM10gPC0gIlN0cm9uZ2x5XG5EaXNhZ3JlZSIKbmFtZXMocmF0aW5nQ291bnQpWzVdIDwtICJTbGlnaHRseVxuRGlzYWdyZWUiCm5hbWVzKHJhdGluZ0NvdW50KVs3XSA8LSAiU2xpZ2h0bHlcbkFncmVlIgpuYW1lcyhyYXRpbmdDb3VudClbOV0gPC0gIlN0cm9uZ2x5XG5BZ3JlZSIKcmF0aW5nQ291bnQKCmxpa2VydChRdWVzdGlvbiB+IC58IEd1aWRlLCBkYXRhPXJhdGluZ0NvdW50LCBsYXlvdXQ9YygxLDIpLAogICAgICAgc2NhbGVzPWxpc3QoeT1saXN0KHJlbGF0aW9uPSJmcmVlIikpLGJldHdlZW49bGlzdCh5PTIuNSksCiAgICAgICBzdHJpcC5sZWZ0PUZBTFNFLCBzdHJpcD1GQUxTRSwKICAgICAgIHBhci5zdHJpcC50ZXh0PWxpc3QoY2V4PTEsIGxpbmVzPTIpLCB5bGFiPU5VTEwsIGNleD0xLjIsCiAgICAgICB4bGltPWMoLTEwMCwtNTAsIC0yNSwgMCwgMjUsIDUwLCA3NSwgMTAwKSwKICAgICAgIFJlZmVyZW5jZVplcm89NCwgYXMucGVyY2VudD0ibm9SaWdodEF4aXMiLAogICAgICAgcmVmZXJlbmNlLmxpbmUuY29sPSJibGFjayIsCiAgICAgICBjb2w9YygiI0QzMTgxOSIsICIjRkY3OTJFIiwgIiNGRkFFNzMiLCAiI0RFRDlEOSIsICIjNzRBRUQ1IiwgIiMzODgxQjgiLCAiIzBFNTI5RiIpLAogICAgICAgYm9yZGVycyA9IGxpc3QoKSwKICAgICAgIHBvc2l0aXZlLm9yZGVyPUZBTFNFLAogICAgICAgbWFpbiA9IGxpc3QoIiIpLAogICAgICAgeGxhYj0iUHJvcG9ydGlvbiAoJSkiLAogICAgICAgYXV0by5rZXk9bGlzdChzcGFjZT0iYm90dG9tIiwgcm93cz0xLCByZXZlcnNlPUZBTFNFLCBwYWRkaW5nLnRleHQ9MSwKICAgICAgICAgICAgICAgICAgICAgcmVjdD0gbGlzdChjb2w9YygiI0QzMTgxOSIsICIjRkY3OTJFIiwgIiNGRkFFNzMiLCAiI0RFRDlEOSIsICIjNzRBRUQ1IiwgIiMzODgxQjgiLCAiIzBFNTI5RiIpLCAjIDwtIFNwZWNpZnkgY29sb3JzIGFnYWluIChmb3Iga2V5cykKICAgICAgICAgICAgICAgICAgICBib3JkZXIgPSAiYmxhY2siKSkpCgojIGV4cG9ydCB0byBwZGY6IDQuMCB4IDguNSBpbmNoCmBgYAoKYGBge3J9CnJhdGluZ1BhcnRpY2lwYW50TG9uZyA9IHBpdm90X2xvbmdlcihyYXRpbmdQYXJ0aWNpcGFudCwgY29scyA9IDU6OSwgbmFtZXNfdG8gPSAiUXVlc3Rpb24iLCB2YWx1ZXNfdG8gPSAiUmF0aW5nIikKcmF0aW5nUGFydGljaXBhbnRMb25nCgp3aWxjb3ggPC0gcmF0aW5nUGFydGljaXBhbnRMb25nICU+JQogIGdyb3VwX2J5KFF1ZXN0aW9uKSAlPiUKICB3aWxjb3hfdGVzdChSYXRpbmcgfiBHdWlkZSwgcGFpcmVkPVRSVUUpICU+JQogIGFkZF9zaWduaWZpY2FuY2UoInAiKQp3aWxjb3gKYGBgCgo=